summaryrefslogtreecommitdiff
path: root/gettext-tools/gnulib-lib
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2014-12-24 07:38:37 +0000
committer <>2015-02-02 12:02:29 +0000
commit482840e61f86ca321838a91e902c41d40c098bbb (patch)
tree01ea2e242fd2792d19fe192476601587901db794 /gettext-tools/gnulib-lib
downloadgettext-tarball-482840e61f86ca321838a91e902c41d40c098bbb.tar.gz
Imported from /home/lorry/working-area/delta_gettext-tarball/gettext-0.19.4.tar.xz.gettext-0.19.4
Diffstat (limited to 'gettext-tools/gnulib-lib')
-rw-r--r--gettext-tools/gnulib-lib/Makefile.am75
-rw-r--r--gettext-tools/gnulib-lib/Makefile.gnulib4301
-rw-r--r--gettext-tools/gnulib-lib/Makefile.in5013
-rw-r--r--gettext-tools/gnulib-lib/acl-errno-valid.c52
-rw-r--r--gettext-tools/gnulib-lib/acl-internal.h253
-rw-r--r--gettext-tools/gnulib-lib/acl.h35
-rw-r--r--gettext-tools/gnulib-lib/acl_entries.c75
-rw-r--r--gettext-tools/gnulib-lib/addext.c97
-rw-r--r--gettext-tools/gnulib-lib/alignof.h50
-rw-r--r--gettext-tools/gnulib-lib/alloca.in.h68
-rw-r--r--gettext-tools/gnulib-lib/allocator.c5
-rw-r--r--gettext-tools/gnulib-lib/allocator.h58
-rw-r--r--gettext-tools/gnulib-lib/areadlink.c56
-rw-r--r--gettext-tools/gnulib-lib/areadlink.h33
-rw-r--r--gettext-tools/gnulib-lib/argmatch.c277
-rw-r--r--gettext-tools/gnulib-lib/argmatch.h111
-rw-r--r--gettext-tools/gnulib-lib/asnprintf.c34
-rw-r--r--gettext-tools/gnulib-lib/asprintf.c39
-rw-r--r--gettext-tools/gnulib-lib/atexit.c13
-rw-r--r--gettext-tools/gnulib-lib/backupfile.c235
-rw-r--r--gettext-tools/gnulib-lib/backupfile.h61
-rw-r--r--gettext-tools/gnulib-lib/basename.c84
-rw-r--r--gettext-tools/gnulib-lib/basename.h43
-rw-r--r--gettext-tools/gnulib-lib/binary-io.c3
-rw-r--r--gettext-tools/gnulib-lib/binary-io.h75
-rw-r--r--gettext-tools/gnulib-lib/byteswap.in.h44
-rw-r--r--gettext-tools/gnulib-lib/c-ctype.c395
-rw-r--r--gettext-tools/gnulib-lib/c-ctype.h295
-rw-r--r--gettext-tools/gnulib-lib/c-strcase.h56
-rw-r--r--gettext-tools/gnulib-lib/c-strcasecmp.c56
-rw-r--r--gettext-tools/gnulib-lib/c-strcaseeq.h184
-rw-r--r--gettext-tools/gnulib-lib/c-strcasestr.c77
-rw-r--r--gettext-tools/gnulib-lib/c-strcasestr.h36
-rw-r--r--gettext-tools/gnulib-lib/c-strncasecmp.c56
-rw-r--r--gettext-tools/gnulib-lib/c-strstr.c32
-rw-r--r--gettext-tools/gnulib-lib/c-strstr.h44
-rw-r--r--gettext-tools/gnulib-lib/canonicalize-lgpl.c411
-rw-r--r--gettext-tools/gnulib-lib/careadlinkat.c160
-rw-r--r--gettext-tools/gnulib-lib/careadlinkat.h67
-rw-r--r--gettext-tools/gnulib-lib/classpath.c122
-rw-r--r--gettext-tools/gnulib-lib/classpath.h33
-rw-r--r--gettext-tools/gnulib-lib/clean-temp.c783
-rw-r--r--gettext-tools/gnulib-lib/clean-temp.h142
-rw-r--r--gettext-tools/gnulib-lib/cloexec.c83
-rw-r--r--gettext-tools/gnulib-lib/cloexec.h38
-rw-r--r--gettext-tools/gnulib-lib/close.c69
-rw-r--r--gettext-tools/gnulib-lib/closedir.c67
-rw-r--r--gettext-tools/gnulib-lib/closeout.c87
-rw-r--r--gettext-tools/gnulib-lib/closeout.h30
-rw-r--r--gettext-tools/gnulib-lib/concat-filename.c73
-rw-r--r--gettext-tools/gnulib-lib/concat-filename.h41
-rw-r--r--gettext-tools/gnulib-lib/config.charset684
-rw-r--r--gettext-tools/gnulib-lib/copy-acl.c61
-rw-r--r--gettext-tools/gnulib-lib/copy-file.c218
-rw-r--r--gettext-tools/gnulib-lib/copy-file.h54
-rw-r--r--gettext-tools/gnulib-lib/csharpcomp.c573
-rw-r--r--gettext-tools/gnulib-lib/csharpcomp.h40
-rw-r--r--gettext-tools/gnulib-lib/csharpexec.c345
-rw-r--r--gettext-tools/gnulib-lib/csharpexec.h43
-rw-r--r--gettext-tools/gnulib-lib/diffseq.h425
-rw-r--r--gettext-tools/gnulib-lib/dirent-private.h40
-rw-r--r--gettext-tools/gnulib-lib/dirent.in.h258
-rw-r--r--gettext-tools/gnulib-lib/dosname.h53
-rw-r--r--gettext-tools/gnulib-lib/dup-safer-flag.c38
-rw-r--r--gettext-tools/gnulib-lib/dup-safer.c34
-rw-r--r--gettext-tools/gnulib-lib/dup2.c164
-rw-r--r--gettext-tools/gnulib-lib/errno.in.h279
-rw-r--r--gettext-tools/gnulib-lib/error-progname.c40
-rw-r--r--gettext-tools/gnulib-lib/error-progname.h52
-rw-r--r--gettext-tools/gnulib-lib/error.c406
-rw-r--r--gettext-tools/gnulib-lib/error.h74
-rw-r--r--gettext-tools/gnulib-lib/execute.c280
-rw-r--r--gettext-tools/gnulib-lib/execute.h44
-rw-r--r--gettext-tools/gnulib-lib/exitfail.c24
-rw-r--r--gettext-tools/gnulib-lib/exitfail.h18
-rw-r--r--gettext-tools/gnulib-lib/fatal-signal.c286
-rw-r--r--gettext-tools/gnulib-lib/fatal-signal.h76
-rw-r--r--gettext-tools/gnulib-lib/fcntl.c327
-rw-r--r--gettext-tools/gnulib-lib/fcntl.in.h363
-rw-r--r--gettext-tools/gnulib-lib/fd-hook.c116
-rw-r--r--gettext-tools/gnulib-lib/fd-hook.h119
-rw-r--r--gettext-tools/gnulib-lib/fd-ostream.c219
-rw-r--r--gettext-tools/gnulib-lib/fd-ostream.h137
-rw-r--r--gettext-tools/gnulib-lib/fd-ostream.oo.c168
-rw-r--r--gettext-tools/gnulib-lib/fd-ostream.oo.h48
-rw-r--r--gettext-tools/gnulib-lib/fd-safer-flag.c52
-rw-r--r--gettext-tools/gnulib-lib/fd-safer.c49
-rw-r--r--gettext-tools/gnulib-lib/fd_ostream.priv.h14
-rw-r--r--gettext-tools/gnulib-lib/fd_ostream.vt.h6
-rw-r--r--gettext-tools/gnulib-lib/file-has-acl.c919
-rw-r--r--gettext-tools/gnulib-lib/file-ostream.c120
-rw-r--r--gettext-tools/gnulib-lib/file-ostream.h135
-rw-r--r--gettext-tools/gnulib-lib/file-ostream.oo.c66
-rw-r--r--gettext-tools/gnulib-lib/file-ostream.oo.h46
-rw-r--r--gettext-tools/gnulib-lib/file_ostream.priv.h11
-rw-r--r--gettext-tools/gnulib-lib/file_ostream.vt.h6
-rw-r--r--gettext-tools/gnulib-lib/filename.h54
-rw-r--r--gettext-tools/gnulib-lib/findprog.c138
-rw-r--r--gettext-tools/gnulib-lib/findprog.h37
-rw-r--r--gettext-tools/gnulib-lib/float+.h147
-rw-r--r--gettext-tools/gnulib-lib/float.c33
-rw-r--r--gettext-tools/gnulib-lib/float.in.h188
-rw-r--r--gettext-tools/gnulib-lib/fnmatch.c354
-rw-r--r--gettext-tools/gnulib-lib/fnmatch.in.h67
-rw-r--r--gettext-tools/gnulib-lib/fnmatch_loop.c1278
-rw-r--r--gettext-tools/gnulib-lib/fopen.c110
-rw-r--r--gettext-tools/gnulib-lib/fstat.c88
-rw-r--r--gettext-tools/gnulib-lib/fstrcmp.c237
-rw-r--r--gettext-tools/gnulib-lib/fstrcmp.h45
-rw-r--r--gettext-tools/gnulib-lib/full-write.c79
-rw-r--r--gettext-tools/gnulib-lib/full-write.h34
-rw-r--r--gettext-tools/gnulib-lib/fwriteerror.c181
-rw-r--r--gettext-tools/gnulib-lib/fwriteerror.h62
-rw-r--r--gettext-tools/gnulib-lib/gcd.c87
-rw-r--r--gettext-tools/gnulib-lib/gcd.h34
-rw-r--r--gettext-tools/gnulib-lib/getdelim.c135
-rw-r--r--gettext-tools/gnulib-lib/getdtablesize.c115
-rw-r--r--gettext-tools/gnulib-lib/getline.c27
-rw-r--r--gettext-tools/gnulib-lib/getopt.c1245
-rw-r--r--gettext-tools/gnulib-lib/getopt.in.h263
-rw-r--r--gettext-tools/gnulib-lib/getopt1.c170
-rw-r--r--gettext-tools/gnulib-lib/getopt_int.h135
-rw-r--r--gettext-tools/gnulib-lib/gettext.h287
-rw-r--r--gettext-tools/gnulib-lib/gettimeofday.c154
-rw-r--r--gettext-tools/gnulib-lib/gl_anyhash_list1.h27
-rw-r--r--gettext-tools/gnulib-lib/gl_anyhash_list2.h138
-rw-r--r--gettext-tools/gnulib-lib/gl_anylinked_list1.h48
-rw-r--r--gettext-tools/gnulib-lib/gl_anylinked_list2.h1195
-rw-r--r--gettext-tools/gnulib-lib/gl_array_list.c680
-rw-r--r--gettext-tools/gnulib-lib/gl_array_list.h34
-rw-r--r--gettext-tools/gnulib-lib/gl_linkedhash_list.c124
-rw-r--r--gettext-tools/gnulib-lib/gl_linkedhash_list.h34
-rw-r--r--gettext-tools/gnulib-lib/gl_list.c3
-rw-r--r--gettext-tools/gnulib-lib/gl_list.h841
-rw-r--r--gettext-tools/gnulib-lib/gl_xlist.c3
-rw-r--r--gettext-tools/gnulib-lib/gl_xlist.h177
-rw-r--r--gettext-tools/gnulib-lib/glib.in.h98
-rw-r--r--gettext-tools/gnulib-lib/glib/ghash.c816
-rw-r--r--gettext-tools/gnulib-lib/glib/ghash.in.h132
-rw-r--r--gettext-tools/gnulib-lib/glib/glist.c688
-rw-r--r--gettext-tools/gnulib-lib/glib/glist.in.h136
-rw-r--r--gettext-tools/gnulib-lib/glib/gmessages.c68
-rw-r--r--gettext-tools/gnulib-lib/glib/gprimes.c98
-rw-r--r--gettext-tools/gnulib-lib/glib/gprimes.in.h51
-rw-r--r--gettext-tools/gnulib-lib/glib/gstrfuncs.c2848
-rw-r--r--gettext-tools/gnulib-lib/glib/gstrfuncs.in.h269
-rw-r--r--gettext-tools/gnulib-lib/glib/gstring.c958
-rw-r--r--gettext-tools/gnulib-lib/glib/gstring.in.h179
-rw-r--r--gettext-tools/gnulib-lib/glib/gtypes.in.h430
-rw-r--r--gettext-tools/gnulib-lib/glibconfig.in.h189
-rw-r--r--gettext-tools/gnulib-lib/glthread/lock.c1057
-rw-r--r--gettext-tools/gnulib-lib/glthread/lock.h927
-rw-r--r--gettext-tools/gnulib-lib/glthread/threadlib.c73
-rw-r--r--gettext-tools/gnulib-lib/glthread/tls.c61
-rw-r--r--gettext-tools/gnulib-lib/glthread/tls.h299
-rw-r--r--gettext-tools/gnulib-lib/hash.c383
-rw-r--r--gettext-tools/gnulib-lib/hash.h90
-rw-r--r--gettext-tools/gnulib-lib/html-ostream.c338
-rw-r--r--gettext-tools/gnulib-lib/html-ostream.h158
-rw-r--r--gettext-tools/gnulib-lib/html-ostream.oo.c277
-rw-r--r--gettext-tools/gnulib-lib/html-ostream.oo.h58
-rw-r--r--gettext-tools/gnulib-lib/html-styled-ostream.c227
-rw-r--r--gettext-tools/gnulib-lib/html-styled-ostream.h160
-rw-r--r--gettext-tools/gnulib-lib/html-styled-ostream.oo.c158
-rw-r--r--gettext-tools/gnulib-lib/html-styled-ostream.oo.h48
-rw-r--r--gettext-tools/gnulib-lib/html_ostream.priv.h21
-rw-r--r--gettext-tools/gnulib-lib/html_ostream.vt.h8
-rw-r--r--gettext-tools/gnulib-lib/html_styled_ostream.priv.h14
-rw-r--r--gettext-tools/gnulib-lib/html_styled_ostream.vt.h6
-rw-r--r--gettext-tools/gnulib-lib/iconv.c449
-rw-r--r--gettext-tools/gnulib-lib/iconv.in.h110
-rw-r--r--gettext-tools/gnulib-lib/iconv_close.c46
-rw-r--r--gettext-tools/gnulib-lib/iconv_open-aix.gperf44
-rw-r--r--gettext-tools/gnulib-lib/iconv_open-aix.h256
-rw-r--r--gettext-tools/gnulib-lib/iconv_open-hpux.gperf56
-rw-r--r--gettext-tools/gnulib-lib/iconv_open-hpux.h299
-rw-r--r--gettext-tools/gnulib-lib/iconv_open-irix.gperf31
-rw-r--r--gettext-tools/gnulib-lib/iconv_open-irix.h199
-rw-r--r--gettext-tools/gnulib-lib/iconv_open-osf.gperf50
-rw-r--r--gettext-tools/gnulib-lib/iconv_open-osf.h278
-rw-r--r--gettext-tools/gnulib-lib/iconv_open-solaris.gperf30
-rw-r--r--gettext-tools/gnulib-lib/iconv_open-solaris.h190
-rw-r--r--gettext-tools/gnulib-lib/iconv_open.c172
-rw-r--r--gettext-tools/gnulib-lib/iconveh.h41
-rw-r--r--gettext-tools/gnulib-lib/ignore-value.h50
-rw-r--r--gettext-tools/gnulib-lib/intprops.h320
-rw-r--r--gettext-tools/gnulib-lib/iswblank.c26
-rw-r--r--gettext-tools/gnulib-lib/itold.c28
-rw-r--r--gettext-tools/gnulib-lib/javacomp.c2350
-rw-r--r--gettext-tools/gnulib-lib/javacomp.h75
-rw-r--r--gettext-tools/gnulib-lib/javaexec.c429
-rw-r--r--gettext-tools/gnulib-lib/javaexec.h50
-rw-r--r--gettext-tools/gnulib-lib/javaversion.c119
-rw-r--r--gettext-tools/gnulib-lib/javaversion.classbin0 -> 510 bytes
-rw-r--r--gettext-tools/gnulib-lib/javaversion.h39
-rw-r--r--gettext-tools/gnulib-lib/javaversion.java31
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-additional-sel.c501
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-additional-sel.h98
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-attr-sel.c236
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-attr-sel.h74
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-cascade.c215
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-cascade.h74
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-declaration.c823
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-declaration.h136
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-doc-handler.c275
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-doc-handler.h298
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-enc-handler.c187
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-enc-handler.h94
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-fonts.c947
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-fonts.h315
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-input.c1183
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-input.h174
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-num.c312
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-num.h127
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-om-parser.c1122
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-om-parser.h98
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-parser.c4524
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-parser.h128
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-parsing-location.c173
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-parsing-location.h70
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-prop-list.c402
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-prop-list.h80
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-pseudo.c167
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-pseudo.h64
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-rgb.c678
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-rgb.h94
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-sel-eng.c1572
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-sel-eng.h114
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-selector.c307
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-selector.h95
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-simple-sel.c325
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-simple-sel.h130
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-statement.c2791
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-statement.h440
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-string.c169
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-string.h76
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-style.c2852
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-style.h339
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-stylesheet.c179
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-stylesheet.h102
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-term.c792
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-term.h190
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-tknzr.c2764
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-tknzr.h115
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-token.c637
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-token.h212
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-utils.c1357
-rw-r--r--gettext-tools/gnulib-lib/libcroco/cr-utils.h249
-rw-r--r--gettext-tools/gnulib-lib/libcroco/libcroco-config.h18
-rw-r--r--gettext-tools/gnulib-lib/libcroco/libcroco.h44
-rw-r--r--gettext-tools/gnulib-lib/libunistring.valgrind9
-rw-r--r--gettext-tools/gnulib-lib/libxml/COPYING27
-rw-r--r--gettext-tools/gnulib-lib/libxml/DOCBparser.c305
-rw-r--r--gettext-tools/gnulib-lib/libxml/DOCBparser.in.h96
-rw-r--r--gettext-tools/gnulib-lib/libxml/HTMLparser.c6276
-rw-r--r--gettext-tools/gnulib-lib/libxml/HTMLparser.in.h303
-rw-r--r--gettext-tools/gnulib-lib/libxml/HTMLtree.c1213
-rw-r--r--gettext-tools/gnulib-lib/libxml/HTMLtree.in.h147
-rw-r--r--gettext-tools/gnulib-lib/libxml/SAX.c180
-rw-r--r--gettext-tools/gnulib-lib/libxml/SAX.in.h173
-rw-r--r--gettext-tools/gnulib-lib/libxml/SAX2.c2891
-rw-r--r--gettext-tools/gnulib-lib/libxml/SAX2.in.h176
-rw-r--r--gettext-tools/gnulib-lib/libxml/c14n.c1928
-rw-r--r--gettext-tools/gnulib-lib/libxml/c14n.in.h105
-rw-r--r--gettext-tools/gnulib-lib/libxml/catalog.c3788
-rw-r--r--gettext-tools/gnulib-lib/libxml/catalog.in.h182
-rw-r--r--gettext-tools/gnulib-lib/libxml/chvalid.c336
-rw-r--r--gettext-tools/gnulib-lib/libxml/chvalid.in.h230
-rw-r--r--gettext-tools/gnulib-lib/libxml/debugXML.c3264
-rw-r--r--gettext-tools/gnulib-lib/libxml/debugXML.in.h217
-rw-r--r--gettext-tools/gnulib-lib/libxml/dict.c901
-rw-r--r--gettext-tools/gnulib-lib/libxml/dict.in.h69
-rw-r--r--gettext-tools/gnulib-lib/libxml/elfgcchack.h0
-rw-r--r--gettext-tools/gnulib-lib/libxml/encoding.c3295
-rw-r--r--gettext-tools/gnulib-lib/libxml/encoding.in.h226
-rw-r--r--gettext-tools/gnulib-lib/libxml/entities.c966
-rw-r--r--gettext-tools/gnulib-lib/libxml/entities.in.h140
-rw-r--r--gettext-tools/gnulib-lib/libxml/error.c986
-rw-r--r--gettext-tools/gnulib-lib/libxml/globals.c1094
-rw-r--r--gettext-tools/gnulib-lib/libxml/globals.in.h455
-rw-r--r--gettext-tools/gnulib-lib/libxml/hash.c1079
-rw-r--r--gettext-tools/gnulib-lib/libxml/hash.in.h233
-rw-r--r--gettext-tools/gnulib-lib/libxml/legacy.c1343
-rw-r--r--gettext-tools/gnulib-lib/libxml/libxml.h79
-rw-r--r--gettext-tools/gnulib-lib/libxml/list.c779
-rw-r--r--gettext-tools/gnulib-lib/libxml/list.in.h137
-rw-r--r--gettext-tools/gnulib-lib/libxml/nanoftp.c2109
-rw-r--r--gettext-tools/gnulib-lib/libxml/nanoftp.in.h143
-rw-r--r--gettext-tools/gnulib-lib/libxml/nanohttp.c1791
-rw-r--r--gettext-tools/gnulib-lib/libxml/nanohttp.in.h81
-rw-r--r--gettext-tools/gnulib-lib/libxml/parser.c13614
-rw-r--r--gettext-tools/gnulib-lib/libxml/parser.in.h1220
-rw-r--r--gettext-tools/gnulib-lib/libxml/parserInternals.c2061
-rw-r--r--gettext-tools/gnulib-lib/libxml/parserInternals.in.h602
-rw-r--r--gettext-tools/gnulib-lib/libxml/pattern.c2607
-rw-r--r--gettext-tools/gnulib-lib/libxml/pattern.in.h100
-rw-r--r--gettext-tools/gnulib-lib/libxml/relaxng.c10815
-rw-r--r--gettext-tools/gnulib-lib/libxml/relaxng.in.h196
-rw-r--r--gettext-tools/gnulib-lib/libxml/schemasInternals.in.h958
-rw-r--r--gettext-tools/gnulib-lib/libxml/schematron.c1730
-rw-r--r--gettext-tools/gnulib-lib/libxml/schematron.in.h124
-rw-r--r--gettext-tools/gnulib-lib/libxml/threads.c867
-rw-r--r--gettext-tools/gnulib-lib/libxml/threads.in.h80
-rw-r--r--gettext-tools/gnulib-lib/libxml/tree.c9537
-rw-r--r--gettext-tools/gnulib-lib/libxml/tree.in.h1208
-rw-r--r--gettext-tools/gnulib-lib/libxml/uri.c2483
-rw-r--r--gettext-tools/gnulib-lib/libxml/uri.in.h89
-rw-r--r--gettext-tools/gnulib-lib/libxml/valid.c6955
-rw-r--r--gettext-tools/gnulib-lib/libxml/valid.in.h458
-rw-r--r--gettext-tools/gnulib-lib/libxml/xinclude.c2555
-rw-r--r--gettext-tools/gnulib-lib/libxml/xinclude.in.h125
-rw-r--r--gettext-tools/gnulib-lib/libxml/xlink.c183
-rw-r--r--gettext-tools/gnulib-lib/libxml/xlink.in.h189
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlIO.c3850
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlIO.in.h360
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlautomata.in.h146
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlerror.in.h936
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlexports.in.h157
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlmemory.c1044
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlmemory.in.h222
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlmodule.c445
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlmodule.in.h57
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlreader.c5659
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlreader.in.h408
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlregexp.c7959
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlregexp.in.h216
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlsave.c2406
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlsave.in.h84
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlschemas.c28654
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlschemas.in.h198
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlschemastypes.c6113
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlschemastypes.in.h151
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlstring.c984
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlstring.in.h140
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlunicode.c3179
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlunicode.in.h202
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlversion.in.h405
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlwriter.c4615
-rw-r--r--gettext-tools/gnulib-lib/libxml/xmlwriter.in.h459
-rw-r--r--gettext-tools/gnulib-lib/libxml/xpath.c15066
-rw-r--r--gettext-tools/gnulib-lib/libxml/xpath.in.h543
-rw-r--r--gettext-tools/gnulib-lib/libxml/xpathInternals.in.h630
-rw-r--r--gettext-tools/gnulib-lib/libxml/xpointer.c3003
-rw-r--r--gettext-tools/gnulib-lib/libxml/xpointer.in.h114
-rw-r--r--gettext-tools/gnulib-lib/localcharset.c579
-rw-r--r--gettext-tools/gnulib-lib/localcharset.h40
-rw-r--r--gettext-tools/gnulib-lib/locale.in.h216
-rw-r--r--gettext-tools/gnulib-lib/localename.c2958
-rw-r--r--gettext-tools/gnulib-lib/localename.h99
-rw-r--r--gettext-tools/gnulib-lib/lstat.c97
-rw-r--r--gettext-tools/gnulib-lib/malloc.c56
-rw-r--r--gettext-tools/gnulib-lib/malloca.c149
-rw-r--r--gettext-tools/gnulib-lib/malloca.h133
-rw-r--r--gettext-tools/gnulib-lib/malloca.valgrind7
-rw-r--r--gettext-tools/gnulib-lib/mbchar.c37
-rw-r--r--gettext-tools/gnulib-lib/mbchar.h360
-rw-r--r--gettext-tools/gnulib-lib/mbiter.c3
-rw-r--r--gettext-tools/gnulib-lib/mbiter.h225
-rw-r--r--gettext-tools/gnulib-lib/mbrtowc.c407
-rw-r--r--gettext-tools/gnulib-lib/mbsinit.c61
-rw-r--r--gettext-tools/gnulib-lib/mbslen.c44
-rw-r--r--gettext-tools/gnulib-lib/mbsrtowcs-impl.h122
-rw-r--r--gettext-tools/gnulib-lib/mbsrtowcs-state.c37
-rw-r--r--gettext-tools/gnulib-lib/mbsrtowcs.c32
-rw-r--r--gettext-tools/gnulib-lib/mbsstr.c384
-rw-r--r--gettext-tools/gnulib-lib/mbswidth.c193
-rw-r--r--gettext-tools/gnulib-lib/mbswidth.h60
-rw-r--r--gettext-tools/gnulib-lib/mbuiter.c3
-rw-r--r--gettext-tools/gnulib-lib/mbuiter.h232
-rw-r--r--gettext-tools/gnulib-lib/memchr.c172
-rw-r--r--gettext-tools/gnulib-lib/memchr.valgrind14
-rw-r--r--gettext-tools/gnulib-lib/memmove.c26
-rw-r--r--gettext-tools/gnulib-lib/memset.c29
-rw-r--r--gettext-tools/gnulib-lib/minmax.h60
-rw-r--r--gettext-tools/gnulib-lib/mkdtemp.c39
-rw-r--r--gettext-tools/gnulib-lib/moo.h248
-rw-r--r--gettext-tools/gnulib-lib/msvc-inval.c129
-rw-r--r--gettext-tools/gnulib-lib/msvc-inval.h222
-rw-r--r--gettext-tools/gnulib-lib/msvc-nothrow.c49
-rw-r--r--gettext-tools/gnulib-lib/msvc-nothrow.h43
-rw-r--r--gettext-tools/gnulib-lib/obstack.c353
-rw-r--r--gettext-tools/gnulib-lib/obstack.h531
-rw-r--r--gettext-tools/gnulib-lib/open.c181
-rw-r--r--gettext-tools/gnulib-lib/opendir.c148
-rw-r--r--gettext-tools/gnulib-lib/ostream.c122
-rw-r--r--gettext-tools/gnulib-lib/ostream.h141
-rw-r--r--gettext-tools/gnulib-lib/ostream.oo.c36
-rw-r--r--gettext-tools/gnulib-lib/ostream.oo.h64
-rw-r--r--gettext-tools/gnulib-lib/ostream.priv.h7
-rw-r--r--gettext-tools/gnulib-lib/ostream.vt.h6
-rw-r--r--gettext-tools/gnulib-lib/pathmax.h83
-rw-r--r--gettext-tools/gnulib-lib/pipe-filter-aux.c43
-rw-r--r--gettext-tools/gnulib-lib/pipe-filter-aux.h103
-rw-r--r--gettext-tools/gnulib-lib/pipe-filter-ii.c474
-rw-r--r--gettext-tools/gnulib-lib/pipe-filter.h237
-rw-r--r--gettext-tools/gnulib-lib/pipe-safer.c56
-rw-r--r--gettext-tools/gnulib-lib/pipe2-safer.c52
-rw-r--r--gettext-tools/gnulib-lib/pipe2.c168
-rw-r--r--gettext-tools/gnulib-lib/printf-args.c187
-rw-r--r--gettext-tools/gnulib-lib/printf-args.h158
-rw-r--r--gettext-tools/gnulib-lib/printf-parse.c638
-rw-r--r--gettext-tools/gnulib-lib/printf-parse.h193
-rw-r--r--gettext-tools/gnulib-lib/progname.c92
-rw-r--r--gettext-tools/gnulib-lib/progname.h62
-rw-r--r--gettext-tools/gnulib-lib/progreloc.c372
-rw-r--r--gettext-tools/gnulib-lib/propername.c318
-rw-r--r--gettext-tools/gnulib-lib/propername.h106
-rw-r--r--gettext-tools/gnulib-lib/qcopy-acl.c583
-rw-r--r--gettext-tools/gnulib-lib/qset-acl.c676
-rw-r--r--gettext-tools/gnulib-lib/quote.h46
-rw-r--r--gettext-tools/gnulib-lib/quotearg.c968
-rw-r--r--gettext-tools/gnulib-lib/quotearg.h391
-rw-r--r--gettext-tools/gnulib-lib/raise.c79
-rw-r--r--gettext-tools/gnulib-lib/rawmemchr.c136
-rw-r--r--gettext-tools/gnulib-lib/rawmemchr.valgrind12
-rw-r--r--gettext-tools/gnulib-lib/read.c85
-rw-r--r--gettext-tools/gnulib-lib/readdir.c98
-rw-r--r--gettext-tools/gnulib-lib/readlink.c74
-rw-r--r--gettext-tools/gnulib-lib/realloc.c79
-rw-r--r--gettext-tools/gnulib-lib/ref-add.sin29
-rw-r--r--gettext-tools/gnulib-lib/ref-del.sin24
-rw-r--r--gettext-tools/gnulib-lib/relocatable.c496
-rw-r--r--gettext-tools/gnulib-lib/relocatable.h81
-rw-r--r--gettext-tools/gnulib-lib/relocwrapper.c198
-rw-r--r--gettext-tools/gnulib-lib/rmdir.c53
-rw-r--r--gettext-tools/gnulib-lib/safe-read.c77
-rw-r--r--gettext-tools/gnulib-lib/safe-read.h47
-rw-r--r--gettext-tools/gnulib-lib/safe-write.c18
-rw-r--r--gettext-tools/gnulib-lib/safe-write.h37
-rw-r--r--gettext-tools/gnulib-lib/sched.in.h57
-rw-r--r--gettext-tools/gnulib-lib/secure_getenv.c41
-rw-r--r--gettext-tools/gnulib-lib/set-acl.c48
-rw-r--r--gettext-tools/gnulib-lib/setenv.c390
-rw-r--r--gettext-tools/gnulib-lib/setlocale.c938
-rw-r--r--gettext-tools/gnulib-lib/sh-quote.c107
-rw-r--r--gettext-tools/gnulib-lib/sh-quote.h49
-rw-r--r--gettext-tools/gnulib-lib/sig-handler.c3
-rw-r--r--gettext-tools/gnulib-lib/sig-handler.h54
-rw-r--r--gettext-tools/gnulib-lib/sigaction.c204
-rw-r--r--gettext-tools/gnulib-lib/signal.in.h461
-rw-r--r--gettext-tools/gnulib-lib/sigprocmask.c349
-rw-r--r--gettext-tools/gnulib-lib/size_max.h30
-rw-r--r--gettext-tools/gnulib-lib/snprintf.c71
-rw-r--r--gettext-tools/gnulib-lib/spawn-pipe.c454
-rw-r--r--gettext-tools/gnulib-lib/spawn-pipe.h147
-rw-r--r--gettext-tools/gnulib-lib/spawn.in.h881
-rw-r--r--gettext-tools/gnulib-lib/spawn_faction_addclose.c69
-rw-r--r--gettext-tools/gnulib-lib/spawn_faction_adddup2.c70
-rw-r--r--gettext-tools/gnulib-lib/spawn_faction_addopen.c73
-rw-r--r--gettext-tools/gnulib-lib/spawn_faction_destroy.c31
-rw-r--r--gettext-tools/gnulib-lib/spawn_faction_init.c56
-rw-r--r--gettext-tools/gnulib-lib/spawn_int.h62
-rw-r--r--gettext-tools/gnulib-lib/spawnattr_destroy.c28
-rw-r--r--gettext-tools/gnulib-lib/spawnattr_init.c33
-rw-r--r--gettext-tools/gnulib-lib/spawnattr_setflags.c45
-rw-r--r--gettext-tools/gnulib-lib/spawnattr_setsigmask.c33
-rw-r--r--gettext-tools/gnulib-lib/spawni.c374
-rw-r--r--gettext-tools/gnulib-lib/spawnp.c33
-rw-r--r--gettext-tools/gnulib-lib/stat.c138
-rw-r--r--gettext-tools/gnulib-lib/stdarg.in.h35
-rw-r--r--gettext-tools/gnulib-lib/stdbool.in.h132
-rw-r--r--gettext-tools/gnulib-lib/stddef.in.h86
-rw-r--r--gettext-tools/gnulib-lib/stdint.in.h635
-rw-r--r--gettext-tools/gnulib-lib/stdio-write.c198
-rw-r--r--gettext-tools/gnulib-lib/stdio.in.h1353
-rw-r--r--gettext-tools/gnulib-lib/stdlib.in.h977
-rw-r--r--gettext-tools/gnulib-lib/stpcpy.c49
-rw-r--r--gettext-tools/gnulib-lib/stpncpy.c92
-rw-r--r--gettext-tools/gnulib-lib/str-kmp.h153
-rw-r--r--gettext-tools/gnulib-lib/str-two-way.h452
-rw-r--r--gettext-tools/gnulib-lib/strchrnul.c142
-rw-r--r--gettext-tools/gnulib-lib/strchrnul.valgrind12
-rw-r--r--gettext-tools/gnulib-lib/strcspn.c41
-rw-r--r--gettext-tools/gnulib-lib/streq.h176
-rw-r--r--gettext-tools/gnulib-lib/strerror-override.c302
-rw-r--r--gettext-tools/gnulib-lib/strerror-override.h56
-rw-r--r--gettext-tools/gnulib-lib/strerror.c70
-rw-r--r--gettext-tools/gnulib-lib/striconv.c463
-rw-r--r--gettext-tools/gnulib-lib/striconv.h75
-rw-r--r--gettext-tools/gnulib-lib/striconveh.c1199
-rw-r--r--gettext-tools/gnulib-lib/striconveh.h140
-rw-r--r--gettext-tools/gnulib-lib/striconveha.c352
-rw-r--r--gettext-tools/gnulib-lib/striconveha.h95
-rw-r--r--gettext-tools/gnulib-lib/string.in.h1029
-rw-r--r--gettext-tools/gnulib-lib/strnlen.c30
-rw-r--r--gettext-tools/gnulib-lib/strnlen1.c35
-rw-r--r--gettext-tools/gnulib-lib/strnlen1.h40
-rw-r--r--gettext-tools/gnulib-lib/strpbrk.c41
-rw-r--r--gettext-tools/gnulib-lib/strstr.c82
-rw-r--r--gettext-tools/gnulib-lib/strtol.c433
-rw-r--r--gettext-tools/gnulib-lib/strtoul.c19
-rw-r--r--gettext-tools/gnulib-lib/styled-ostream.c143
-rw-r--r--gettext-tools/gnulib-lib/styled-ostream.h144
-rw-r--r--gettext-tools/gnulib-lib/styled-ostream.oo.c27
-rw-r--r--gettext-tools/gnulib-lib/styled-ostream.oo.h44
-rw-r--r--gettext-tools/gnulib-lib/styled_ostream.priv.h10
-rw-r--r--gettext-tools/gnulib-lib/styled_ostream.vt.h8
-rw-r--r--gettext-tools/gnulib-lib/sys_select.in.h314
-rw-r--r--gettext-tools/gnulib-lib/sys_stat.in.h732
-rw-r--r--gettext-tools/gnulib-lib/sys_time.in.h213
-rw-r--r--gettext-tools/gnulib-lib/sys_types.in.h53
-rw-r--r--gettext-tools/gnulib-lib/sys_wait.in.h129
-rw-r--r--gettext-tools/gnulib-lib/tempname.c306
-rw-r--r--gettext-tools/gnulib-lib/tempname.h50
-rw-r--r--gettext-tools/gnulib-lib/term-ostream.c2043
-rw-r--r--gettext-tools/gnulib-lib/term-ostream.h282
-rw-r--r--gettext-tools/gnulib-lib/term-ostream.oo.c1925
-rw-r--r--gettext-tools/gnulib-lib/term-ostream.oo.h109
-rw-r--r--gettext-tools/gnulib-lib/term-styled-ostream.c688
-rw-r--r--gettext-tools/gnulib-lib/term-styled-ostream.h161
-rw-r--r--gettext-tools/gnulib-lib/term-styled-ostream.oo.c631
-rw-r--r--gettext-tools/gnulib-lib/term-styled-ostream.oo.h49
-rw-r--r--gettext-tools/gnulib-lib/term_ostream.priv.h42
-rw-r--r--gettext-tools/gnulib-lib/term_ostream.vt.h17
-rw-r--r--gettext-tools/gnulib-lib/term_styled_ostream.priv.h24
-rw-r--r--gettext-tools/gnulib-lib/term_styled_ostream.vt.h6
-rw-r--r--gettext-tools/gnulib-lib/terminfo.h114
-rw-r--r--gettext-tools/gnulib-lib/time.in.h274
-rw-r--r--gettext-tools/gnulib-lib/tmpdir.c159
-rw-r--r--gettext-tools/gnulib-lib/tmpdir.h26
-rw-r--r--gettext-tools/gnulib-lib/tparm.c896
-rw-r--r--gettext-tools/gnulib-lib/tputs.c41
-rw-r--r--gettext-tools/gnulib-lib/trim.c129
-rw-r--r--gettext-tools/gnulib-lib/trim.h33
-rw-r--r--gettext-tools/gnulib-lib/uniconv.in.h172
-rw-r--r--gettext-tools/gnulib-lib/uniconv/u8-conv-from-enc.c105
-rw-r--r--gettext-tools/gnulib-lib/unilbrk.in.h110
-rw-r--r--gettext-tools/gnulib-lib/unilbrk/lbrkprop1.h33
-rw-r--r--gettext-tools/gnulib-lib/unilbrk/lbrkprop2.h2942
-rw-r--r--gettext-tools/gnulib-lib/unilbrk/lbrktables.c64
-rw-r--r--gettext-tools/gnulib-lib/unilbrk/lbrktables.h95
-rw-r--r--gettext-tools/gnulib-lib/unilbrk/u8-possible-linebreaks.c261
-rw-r--r--gettext-tools/gnulib-lib/unilbrk/u8-width-linebreaks.c204
-rw-r--r--gettext-tools/gnulib-lib/unilbrk/ulc-common.c51
-rw-r--r--gettext-tools/gnulib-lib/unilbrk/ulc-common.h31
-rw-r--r--gettext-tools/gnulib-lib/unilbrk/ulc-width-linebreaks.c231
-rw-r--r--gettext-tools/gnulib-lib/uniname.in.h46
-rwxr-xr-xgettext-tools/gnulib-lib/uniname/gen-uninames.lisp301
-rw-r--r--gettext-tools/gnulib-lib/uniname/uniname.c516
-rw-r--r--gettext-tools/gnulib-lib/uniname/uninames.h61495
-rw-r--r--gettext-tools/gnulib-lib/unistd--.h32
-rw-r--r--gettext-tools/gnulib-lib/unistd-safer.h31
-rw-r--r--gettext-tools/gnulib-lib/unistd.c3
-rw-r--r--gettext-tools/gnulib-lib/unistd.in.h1590
-rw-r--r--gettext-tools/gnulib-lib/unistr.in.h750
-rw-r--r--gettext-tools/gnulib-lib/unistr/u16-mbtouc-aux.c51
-rw-r--r--gettext-tools/gnulib-lib/unistr/u16-mbtouc.c61
-rw-r--r--gettext-tools/gnulib-lib/unistr/u8-check.c105
-rw-r--r--gettext-tools/gnulib-lib/unistr/u8-mblen.c99
-rw-r--r--gettext-tools/gnulib-lib/unistr/u8-mbtouc-aux.c240
-rw-r--r--gettext-tools/gnulib-lib/unistr/u8-mbtouc-unsafe-aux.c260
-rw-r--r--gettext-tools/gnulib-lib/unistr/u8-mbtouc-unsafe.c271
-rw-r--r--gettext-tools/gnulib-lib/unistr/u8-mbtouc.c250
-rw-r--r--gettext-tools/gnulib-lib/unistr/u8-mbtoucr.c285
-rw-r--r--gettext-tools/gnulib-lib/unistr/u8-prev.c93
-rw-r--r--gettext-tools/gnulib-lib/unistr/u8-uctomb-aux.c69
-rw-r--r--gettext-tools/gnulib-lib/unistr/u8-uctomb.c88
-rw-r--r--gettext-tools/gnulib-lib/unitypes.in.h46
-rw-r--r--gettext-tools/gnulib-lib/uniwidth.in.h72
-rw-r--r--gettext-tools/gnulib-lib/uniwidth/cjk.h37
-rw-r--r--gettext-tools/gnulib-lib/uniwidth/width.c368
-rw-r--r--gettext-tools/gnulib-lib/unlocked-io.h136
-rw-r--r--gettext-tools/gnulib-lib/unsetenv.c127
-rw-r--r--gettext-tools/gnulib-lib/vasnprintf.c5595
-rw-r--r--gettext-tools/gnulib-lib/vasnprintf.h79
-rw-r--r--gettext-tools/gnulib-lib/vasprintf.c50
-rw-r--r--gettext-tools/gnulib-lib/verify.h279
-rw-r--r--gettext-tools/gnulib-lib/vsnprintf.c70
-rw-r--r--gettext-tools/gnulib-lib/w32spawn.h222
-rw-r--r--gettext-tools/gnulib-lib/wait-process.c361
-rw-r--r--gettext-tools/gnulib-lib/wait-process.h74
-rw-r--r--gettext-tools/gnulib-lib/waitpid.c30
-rw-r--r--gettext-tools/gnulib-lib/wchar.in.h1028
-rw-r--r--gettext-tools/gnulib-lib/wctype-h.c4
-rw-r--r--gettext-tools/gnulib-lib/wctype.in.h514
-rw-r--r--gettext-tools/gnulib-lib/wcwidth.c50
-rw-r--r--gettext-tools/gnulib-lib/write.c145
-rw-r--r--gettext-tools/gnulib-lib/xalloc.h158
-rw-r--r--gettext-tools/gnulib-lib/xasprintf.c34
-rw-r--r--gettext-tools/gnulib-lib/xconcat-filename.c41
-rw-r--r--gettext-tools/gnulib-lib/xerror.c96
-rw-r--r--gettext-tools/gnulib-lib/xerror.h45
-rw-r--r--gettext-tools/gnulib-lib/xmalloc.c128
-rw-r--r--gettext-tools/gnulib-lib/xmalloca.c38
-rw-r--r--gettext-tools/gnulib-lib/xmalloca.h64
-rw-r--r--gettext-tools/gnulib-lib/xreadlink.c44
-rw-r--r--gettext-tools/gnulib-lib/xreadlink.h25
-rw-r--r--gettext-tools/gnulib-lib/xsetenv.c38
-rw-r--r--gettext-tools/gnulib-lib/xsetenv.h31
-rw-r--r--gettext-tools/gnulib-lib/xsize.c3
-rw-r--r--gettext-tools/gnulib-lib/xsize.h117
-rw-r--r--gettext-tools/gnulib-lib/xstrdup.c40
-rw-r--r--gettext-tools/gnulib-lib/xstriconv.c62
-rw-r--r--gettext-tools/gnulib-lib/xstriconv.h78
-rw-r--r--gettext-tools/gnulib-lib/xstriconveh.c86
-rw-r--r--gettext-tools/gnulib-lib/xstriconveh.h115
-rw-r--r--gettext-tools/gnulib-lib/xvasprintf.c110
-rw-r--r--gettext-tools/gnulib-lib/xvasprintf.h55
598 files changed, 385345 insertions, 0 deletions
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 <http://www.gnu.org/licenses/>.
+
+## 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 <http://www.gnu.org/licenses/>.
+#
+# 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 <alloca.h> 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 <byteswap.h> 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 <dirent.h> 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 <errno.h> 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 <fcntl.h> 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 <float.h> 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 <fnmatch.h> 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 <getopt.h> 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 <libintl.h> 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 <iconv.h> 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 <locale.h> 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 <sched.h> 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 <signal.h> 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 <spawn.h> 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 <stdarg.h> 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 <stdbool.h> 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 <stddef.h> 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 <stdint.h> 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 <stdio.h> 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 <stdlib.h> 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 <string.h> 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 <sys/select.h> 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 <sys/stat.h> 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 <sys/time.h> 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 <sys/types.h> 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 <sys/wait.h> 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 <time.h> 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
+# <unistd.h> 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 <wchar.h> 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 <wctype.h> 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 <http://www.gnu.org/licenses/>.
+#
+# 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 <libintl.h> 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 <alloca.h> 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 <byteswap.h> 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 <dirent.h> 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 <errno.h> 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 <fcntl.h> 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 <float.h> 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 <fnmatch.h> 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 <getopt.h> 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 <iconv.h> 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 <locale.h> 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 <sched.h> 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 <signal.h> 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 <spawn.h> 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 <stdarg.h> 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 <stdbool.h> 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 <stddef.h> 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 <stdint.h> 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 <stdio.h> 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 <stdlib.h> 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 <string.h> 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 <sys/select.h> 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 <sys/stat.h> 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 <sys/time.h> 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 <sys/types.h> 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 <sys/wait.h> 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 <time.h> 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
+# <unistd.h> 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 <wchar.h> 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 <wctype.h> 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 <http://www.gnu.org/licenses/>.
+
+ Written by Paul Eggert. */
+
+#include <config.h>
+
+#include <acl.h>
+
+#include <errno.h>
+
+/* 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 <http://www.gnu.org/licenses/>.
+
+ Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */
+
+#include "acl.h"
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+/* All systems define the ACL related API in <sys/acl.h>. */
+#if HAVE_SYS_ACL_H
+# include <sys/acl.h>
+#endif
+#if defined HAVE_FACL && ! defined GETACLCNT && defined ACL_CNT
+# define GETACLCNT ACL_CNT
+#endif
+
+/* On Linux, additional ACL related API is available in <acl/libacl.h>. */
+#ifdef HAVE_ACL_LIBACL_H
+# include <acl/libacl.h>
+#endif
+
+/* On HP-UX >= 11.11, additional ACL API is available in <aclv.h>. */
+#if HAVE_ACLV_H
+# include <sys/types.h>
+# include <aclv.h>
+/* HP-UX 11.11 lacks these declarations. */
+extern int acl (char *, int, int, struct acl *);
+extern int aclsort (int, int, struct acl *);
+#endif
+
+#include <errno.h>
+
+#include <limits.h>
+#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 <http://www.gnu.org/licenses/>.
+
+ Written by Paul Eggert. */
+
+#ifndef _GL_ACL_H
+#define _GL_ACL_H 1
+
+#include <stdbool.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+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 <http://www.gnu.org/licenses/>.
+
+ Written by Paul Eggert and Andreas Gruenbacher. */
+
+#include <config.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+/* Written by David MacKenzie <djm@gnu.ai.mit.edu> and Paul Eggert */
+
+#include <config.h>
+
+#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 <limits.h>
+#ifndef _POSIX_NAME_MAX
+# define _POSIX_NAME_MAX 14
+#endif
+
+#include <sys/types.h>
+#if HAVE_STRING_H
+# include <string.h>
+#else
+# include <strings.h>
+#endif
+
+#include <unistd.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _ALIGNOF_H
+#define _ALIGNOF_H
+
+#include <stddef.h>
+
+/* 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
+ <stdalign.h> 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 <class type> struct alignof_helper { char __slot1; type __slot2; };
+# define alignof_slot(type) offsetof (alignof_helper<type>, __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 <http://www.gnu.org/licenses/>. */
+
+/* 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 <malloc.h>
+# define alloca _alloca
+# else
+# if HAVE_ALLOCA_H
+# include <alloca.h>
+# 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 <config.h>
+#include "allocator.h"
+#include <stdlib.h>
+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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert. */
+
+#ifndef _GL_ALLOCATOR_H
+#define _GL_ALLOCATOR_H
+
+#include <stddef.h>
+
+/* 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
+ <http://lists.gnu.org/archive/html/bug-gnulib/2011-04/msg00007.html>. */
+
+ /* 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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Jim Meyering <jim@meyering.net>
+ and Bruno Haible <bruno@clisp.org>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "areadlink.h"
+
+#include "careadlinkat.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Jim Meyering <jim@meyering.net> */
+
+#include <stddef.h>
+
+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 <http://www.gnu.org/licenses/>. */
+
+/* Written by David MacKenzie <djm@ai.mit.edu>
+ Modified by Akim Demaille <demaille@inf.enst.fr> */
+
+#include <config.h>
+
+/* Specification. */
+#include "argmatch.h"
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <djm@gnu.ai.mit.edu>
+ */
+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 <http://www.gnu.org/licenses/>. */
+
+/* Written by David MacKenzie <djm@ai.mit.edu>
+ Modified by Akim Demaille <demaille@inf.enst.fr> */
+
+#ifndef ARGMATCH_H_
+# define ARGMATCH_H_ 1
+
+# include <stddef.h>
+
+# 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "vasnprintf.h"
+
+#include <stdarg.h>
+
+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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#ifdef IN_LIBASPRINTF
+# include "vasprintf.h"
+#else
+# include <stdio.h>
+#endif
+
+#include <stdarg.h>
+
+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 <config.h>
+
+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 <http://www.gnu.org/licenses/>. */
+
+/* Written by David MacKenzie <djm@gnu.ai.mit.edu>.
+ Some algorithms adapted from GNU Emacs. */
+
+#include <config.h>
+
+#include "argmatch.h"
+#include "backupfile.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#if HAVE_STRING_H
+# include <string.h>
+#else
+# include <strings.h>
+#endif
+
+#if HAVE_DIRENT_H
+# include <dirent.h>
+#endif
+
+#include <stdlib.h>
+
+#include "basename.h"
+
+#if HAVE_DIRENT_H
+# define HAVE_DIR 1
+#else
+# define HAVE_DIR 0
+#endif
+
+#include <limits.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "basename.h"
+
+#if !(__GLIBC__ >= 2 || defined __UCLIBC__)
+
+#include <stdio.h>
+#include <assert.h>
+
+#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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _BASENAME_H
+#define _BASENAME_H
+
+/* This is where basename() is declared. */
+#include <string.h>
+
+
+#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 <config.h>
+#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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _BINARY_H
+#define _BINARY_H
+
+/* For systems that distinguish between text and binary I/O.
+ O_BINARY is guaranteed by the gnulib <fcntl.h>. */
+#include <fcntl.h>
+
+/* The MSVC7 <stdio.h> doesn't like to be included after '#define fileno ...',
+ so we include it here first. */
+#include <stdio.h>
+
+#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 <io.h> /* 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 <unistd.h> /* 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 <oskar@osk.mine.nu>, 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 <http://www.gnu.org/licenses/>. */
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* 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 <ctype.h>,
+ except that they have the C (POSIX) locale hardwired, whereas the
+ <ctype.h> 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef C_CTYPE_H
+#define C_CTYPE_H
+
+#include <stdbool.h>
+
+
+#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 <ctype.h>, 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 <ctype.h> 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef C_STRCASE_H
+#define C_STRCASE_H
+
+#include <stddef.h>
+
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "c-strcase.h"
+
+#include <limits.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>. */
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "c-strcasestr.h"
+
+#include <stdbool.h>
+#include <string.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "c-strcase.h"
+
+#include <limits.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "c-strstr.h"
+
+#include <string.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#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 <config.h>
+#endif
+
+#if !HAVE_CANONICALIZE_FILE_NAME || !FUNC_REALPATH_WORKS || defined _LIBC
+
+/* Specification. */
+#include <stdlib.h>
+
+#include <alloca.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#if HAVE_SYS_PARAM_H || defined _LIBC
+# include <sys/param.h>
+#endif
+#include <sys/stat.h>
+#include <errno.h>
+#include <stddef.h>
+
+#ifdef _LIBC
+# include <shlib-compat.h>
+#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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */
+
+#include <config.h>
+
+#include "careadlinkat.h"
+
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+#include <unistd.h>
+
+/* 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()
+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html>
+ 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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */
+
+#ifndef _GL_CAREADLINKAT_H
+#define _GL_CAREADLINKAT_H
+
+#include <fcntl.h>
+#include <unistd.h>
+
+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()
+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html>
+ 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 <fcntl.h>. */
+#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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "classpath.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <stdbool.h>
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+
+#include <config.h>
+
+/* Specification. */
+#include "clean-temp.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# define WIN32_LEAN_AND_MEAN /* avoid including junk */
+# include <windows.h>
+#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 /* <char *> */ volatile subdirs;
+ /* Absolute pathnames of files. */
+ gl_list_t /* <char *> */ 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 /* <int> */ 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
+ <http://msdn.microsoft.com/en-us/library/windows/desktop/ms724451(v=vs.85).aspx>
+ 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _CLEAN_TEMP_H
+#define _CLEAN_TEMP_H
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#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 <http://www.gnu.org/licenses/>.
+
+ The code is taken from glibc/manual/llio.texi */
+
+#include <config.h>
+
+#include "cloexec.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+/* 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 <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <stdbool.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <unistd.h>
+
+#include <errno.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <dirent.h>
+
+#if REPLACE_FCHDIR
+# include <unistd.h>
+#endif
+
+#if HAVE_CLOSEDIR
+
+/* Override closedir(), to keep track of the open file descriptors.
+ Needed because there is a function dirfd(). */
+
+#else
+
+# include <stdlib.h>
+
+# 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "closeout.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <haible@clisp.cons.org>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "concat-filename.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#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 <http://www.gnu.org/licenses/>.
+#
+# 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 <juan.guerrero@gmx.de>"
+ echo "# and Bruno Haible <bruno@clisp.org>."
+ 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 <http://www.gnu.org/licenses/>.
+
+ Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */
+
+#include <config.h>
+
+#include "acl.h"
+
+#include <errno.h>
+
+#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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+
+#include <config.h>
+
+/* Specification. */
+#include "copy-file.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#if HAVE_UTIME || HAVE_UTIMES
+# if HAVE_UTIME_H
+# include <utime.h>
+# else
+# include <sys/utime.h>
+# 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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+#include <alloca.h>
+
+/* Specification. */
+#include "csharpcomp.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _CSHARPCOMP_H
+#define _CSHARPCOMP_H
+
+#include <stdbool.h>
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+#include <alloca.h>
+
+/* Specification. */
+#include "csharpexec.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _CSHARPEXEC_H
+#define _CSHARPEXEC_H
+
+#include <stdbool.h>
+
+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 <http://www.gnu.org/licenses/>. */
+
+
+/* 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,
+ <http://dx.doi.org/10.1007/BF01840446>.
+ 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,
+ <http://dx.doi.org/10.1016/S0019-9958(85)80046-2>. */
+
+/* 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 <limits.h>
+ #include <stdbool.h>
+ #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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _DIRENT_PRIVATE_H
+#define _DIRENT_PRIVATE_H 1
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+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 <dirent.h>.
+ 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 <http://www.gnu.org/licenses/>. */
+
+#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 <sys/types.h>
+
+#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 <http://www.gnu.org/licenses/>.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert and Eric Blake. */
+
+#include <config.h>
+
+/* Specification. */
+#include "unistd-safer.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert. */
+
+#include <config.h>
+
+#include "unistd-safer.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+/* written by Paul Eggert */
+
+#include <config.h>
+
+/* Specification. */
+#include <unistd.h>
+
+#include <errno.h>
+#include <fcntl.h>
+
+#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 <windows.h>
+
+# 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 <errno.h>.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+#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 <winsock2.h>. */
+# 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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+
+#include <config.h>
+
+/* Specification. */
+#include "error-progname.h"
+
+#include <stdio.h>
+
+#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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _ERROR_PROGNAME_H
+#define _ERROR_PROGNAME_H
+
+#include <stdbool.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
+
+#if !_LIBC
+# include <config.h>
+#endif
+
+#include "error.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if !_LIBC && ENABLE_NLS
+# include "gettext.h"
+# define _(msgid) gettext (msgid)
+#endif
+
+#ifdef _LIBC
+# include <libintl.h>
+# include <stdbool.h>
+# include <stdint.h>
+# include <wchar.h>
+# 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 <errno.h>
+# include <limits.h>
+# include <libio/libioP.h>
+
+/* 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 <libio/iolibio.h>
+# define fflush(s) _IO_fflush (s)
+# undef putc
+# define putc(c, fp) _IO_putc (c, fp)
+
+# include <bits/libc-lock.h>
+
+#else /* not _LIBC */
+
+# include <fcntl.h>
+# include <unistd.h>
+
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+/* Get declarations of the native Windows API functions. */
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+
+#include <config.h>
+
+/* Specification. */
+#include "execute.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+
+#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 <process.h>
+# include "w32spawn.h"
+
+#else
+
+/* Unix API. */
+# include <spawn.h>
+
+#endif
+
+/* environ is the exported symbol referencing the internal
+ __cygwin_environ variable on cygwin64:
+ <https://cygwin.com/ml/cygwin/2013-06/msg00228.html>. */
+#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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _EXECUTE_H
+#define _EXECUTE_H
+
+#include <stdbool.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include "exitfail.h"
+
+#include <stdlib.h>
+
+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 <http://www.gnu.org/licenses/>. */
+
+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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+
+#include <config.h>
+
+/* Specification. */
+#include "fatal-signal.h"
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+
+#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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Eric Blake <ebb9@byu.net>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <fcntl.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+#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 <windows.h>
+
+/* 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 <fcntl.h>, 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 <http://www.gnu.org/licenses/>. */
+
+/* written by Paul Eggert */
+
+#if __GNUC__ >= 3
+@PRAGMA_SYSTEM_HEADER@
+#endif
+@PRAGMA_COLUMNS@
+
+#if defined __need_system_fcntl_h
+/* Special invocation convention. */
+
+/* Needed before <sys/stat.h>.
+ May also define off_t to a 64-bit type on native Windows. */
+#include <sys/types.h>
+/* On some systems other than glibc, <sys/stat.h> is a prerequisite of
+ <fcntl.h>. On glibc systems, we would like to avoid namespace pollution.
+ But on glibc systems, <fcntl.h> includes <sys/stat.h> inside an
+ extern "C" { ... } block, which leads to errors in C++ mode with the
+ overridden <sys/stat.h> 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 <sys/stat.h>
+#endif
+#@INCLUDE_NEXT@ @NEXT_FCNTL_H@
+
+#else
+/* Normal invocation convention. */
+
+#ifndef _@GUARD_PREFIX@_FCNTL_H
+
+/* Needed before <sys/stat.h>.
+ May also define off_t to a 64-bit type on native Windows. */
+#include <sys/types.h>
+/* On some systems other than glibc, <sys/stat.h> is a prerequisite of
+ <fcntl.h>. On glibc systems, we would like to avoid namespace pollution.
+ But on glibc systems, <fcntl.h> includes <sys/stat.h> inside an
+ extern "C" { ... } block, which leads to errors in C++ mode with the
+ overridden <sys/stat.h> 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 <sys/stat.h>
+#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 <unistd.h>
+#endif
+
+/* Native Windows platforms declare open(), creat() in <io.h>. */
+#if (@GNULIB_OPEN@ || defined GNULIB_POSIXCHECK) \
+ && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)
+# include <io.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. */
+
+
+/* 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 <limits.h>
+# 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "fd-hook.h"
+
+#include <stdlib.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "fd-ostream.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _FD_OSTREAM_H
+#define _FD_OSTREAM_H
+
+#include <stdbool.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "fd-ostream.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _FD_OSTREAM_H
+#define _FD_OSTREAM_H
+
+#include <stdbool.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert and Eric Blake. */
+
+#include <config.h>
+
+/* Specification. */
+#include "unistd-safer.h"
+
+#include <errno.h>
+#include <unistd.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert. */
+
+#include <config.h>
+
+#include "unistd-safer.h"
+
+#include <errno.h>
+#include <unistd.h>
+
+/* 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 <http://www.gnu.org/licenses/>.
+
+ 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 <config.h>
+
+#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 <sys/acl.h> 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
+ <sys/acl.h> (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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "file-ostream.h"
+
+#include <stdlib.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _FILE_OSTREAM_H
+#define _FILE_OSTREAM_H
+
+#include <stdio.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "file-ostream.h"
+
+#include <stdlib.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _FILE_OSTREAM_H
+#define _FILE_OSTREAM_H
+
+#include <stdio.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+
+#include <config.h>
+
+/* Specification. */
+#include "findprog.h"
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* 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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _FLOATPLUS_H
+#define _FLOATPLUS_H
+
+#include <float.h>
+#include <limits.h>
+
+/* 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 <float.h>.
+ Copyright (C) 2011-2014 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <float.h>
+
+#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 <float.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 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#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
+ <http://lists.gnu.org/archive/html/bug-gnulib/2008-07/msg00063.html>. */
+#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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _LIBC
+# include <config.h>
+#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 <fnmatch.h>
+
+#include <alloca.h>
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <wctype.h>
+# include <wchar.h>
+#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 <shlib-compat.h>
+
+# 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 <http://www.gnu.org/licenses/>. */
+
+#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 <unistd.h>. */
+#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 <http://www.gnu.org/licenses/>. */
+
+/* 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 <locale/weightwc.h>
+# else
+# include <locale/weight.h>
+# 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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2007. */
+
+/* If the user's config.h happens to include <stdio.h>, let it include only
+ the system's <stdio.h> here, so that orig_fopen doesn't recurse to
+ rpl_fopen. */
+#define __need_FILE
+#include <config.h>
+
+/* Get the original definition of fopen. It might be defined as a macro. */
+#include <stdio.h>
+#undef __need_FILE
+
+static FILE *
+orig_fopen (const char *filename, const char *mode)
+{
+ return fopen (filename, mode);
+}
+
+/* Specification. */
+/* Write "stdio.h" here, not <stdio.h>, otherwise OSF/1 5.1 DTK cc eliminates
+ this include because of the preliminary #include <stdio.h> above. */
+#include "stdio.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+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 <http://www.opengroup.org/susv3/basedefs/xbd_chap04.html>
+ 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
+ <http://www.opengroup.org/susv3/functions/fopen.html> 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 <http://www.gnu.org/licenses/>. */
+
+/* If the user's config.h happens to include <sys/stat.h>, let it include only
+ the system's <sys/stat.h> here, so that orig_fstat doesn't recurse to
+ rpl_fstat. */
+#define __need_system_sys_stat_h
+#include <config.h>
+
+/* Get the original definition of fstat. It might be defined as a macro. */
+#include <sys/types.h>
+#include <sys/stat.h>
+#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 <sys/stat.h>, otherwise OSF/1 5.1 DTK cc
+ eliminates this include because of the preliminary #include <sys/stat.h>
+ above. */
+#include "sys/stat.h"
+
+#include <errno.h>
+#include <unistd.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+
+#include <config.h>
+
+/* Specification. */
+#include "fstrcmp.h"
+
+#include <string.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#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 <pmiller@agso.gov.au>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#ifdef FULL_READ
+# include "full-read.h"
+#else
+# include "full-write.h"
+#endif
+
+#include <errno.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <stddef.h>
+
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "fwriteerror.h"
+
+#include <errno.h>
+#include <stdbool.h>
+
+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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+/* 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 <stdio.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* 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 <stdlib.h>
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#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 <http://www.gnu.org/licenses/>. */
+
+/* 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 <config.h>
+
+#include <stdio.h>
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <unistd.h>
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+
+# include <stdio.h>
+
+# 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 <sys/resource.h>
+# 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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Simon Josefsson. */
+
+#include <config.h>
+
+#include <stdio.h>
+
+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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _LIBC
+# include <config.h>
+#endif
+
+#include "getopt.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "gettext.h"
+# define _(msgid) gettext (msgid)
+#endif
+
+#if defined _LIBC && defined USE_IN_LIBIO
+# include <wchar.h>
+#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 <http://www.gnu.org/licenses/>. */
+
+#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
+ <getopt.h>; 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
+ <stdlib.h> includes <getopt.h>, and <config.h> is not a prerequisite for
+ using <stdlib.h>, this file can be included without a prior
+ "#include <config.h>". */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#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 <getopt.h>,
+ 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 <stdlib.h>
+# undef __need_system_stdlib_h
+# include <stdio.h>
+# include <unistd.h>
+# 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 <features.h>, but
+ that does not exist if we are standalone. So: if __GNU_LIBRARY__ is
+ not defined, include <ctype.h>, which will pull in <features.h> 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 <ctype.h>
+#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 <http://www.gnu.org/licenses/>. */
+
+#ifdef _LIBC
+# include <getopt.h>
+#else
+# include <config.h>
+# include "getopt.h"
+#endif
+#include "getopt_int.h"
+
+#include <stdio.h>
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+#include <stdlib.h>
+#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 <stdio.h>
+
+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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _GETOPT_INT_H
+#define _GETOPT_INT_H 1
+
+#include <getopt.h>
+
+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 <libintl.h>.
+ 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 <http://www.gnu.org/licenses/>. */
+
+#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 <libintl.h>
+
+/* 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 <locale.h> a NOP. We don't include <libintl.h>
+ as well because people using "gettext.h" will not include <libintl.h>,
+ and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
+ is OK. */
+#if defined(__sun)
+# include <locale.h>
+#endif
+
+/* Many header files from the libstdc++ coming with g++ 3.3 or newer include
+ <libintl.h>, which chokes if dcgettext is defined as a macro. So include
+ it now, to make later inclusions of <libintl.h> a NOP. */
+#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3)
+# include <cstdlib>
+# if (__GLIBC__ >= 2 && !defined __UCLIBC__) || _GLIBCXX_HAVE_LIBINTL_H
+# include <libintl.h>
+# 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 <string.h>
+
+#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 <stdlib.h>
+#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 <http://www.gnu.org/licenses/>. */
+
+/* written by Jim Meyering */
+
+#include <config.h>
+
+/* Specification. */
+#include <sys/time.h>
+
+#include <time.h>
+
+#if HAVE_SYS_TIMEB_H
+# include <sys/timeb.h>
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "gl_array_list.h"
+
+#include <stdlib.h>
+/* Get memcpy. */
+#include <string.h>
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "gl_linkedhash_list.h"
+
+#include <stdint.h> /* for SIZE_MAX */
+#include <stdlib.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#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 <config.h>
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _GL_LIST_H
+#define _GL_LIST_H
+
+#include <stdbool.h>
+#include <stddef.h>
+
+#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 <config.h>
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#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 <glib/galloca.h>
+#include <glib/garray.h>
+#include <glib/gasyncqueue.h>
+#include <glib/gatomic.h>
+#include <glib/gbacktrace.h>
+#include <glib/gbase64.h>
+#include <glib/gbookmarkfile.h>
+#include <glib/gcache.h>
+#include <glib/gcompletion.h>
+#include <glib/gconvert.h>
+#include <glib/gdataset.h>
+#include <glib/gdate.h>
+#include <glib/gdir.h>
+#include <glib/gerror.h>
+#include <glib/gfileutils.h>
+#endif
+#include <glib/ghash.h>
+#if 0
+#include <glib/ghook.h>
+#include <glib/giochannel.h>
+#include <glib/gkeyfile.h>
+#endif
+#include <glib/glist.h>
+#if 0
+#include <glib/gmacros.h>
+#include <glib/gmain.h>
+#include <glib/gmappedfile.h>
+#include <glib/gmarkup.h>
+#include <glib/gmem.h>
+#include <glib/gmessages.h>
+#include <glib/gnode.h>
+#include <glib/goption.h>
+#include <glib/gpattern.h>
+#endif
+#include <glib/gprimes.h>
+#if 0
+#include <glib/gqsort.h>
+#include <glib/gquark.h>
+#include <glib/gqueue.h>
+#include <glib/grand.h>
+#include <glib/grel.h>
+#include <glib/gscanner.h>
+#include <glib/gshell.h>
+#include <glib/gslist.h>
+#include <glib/gspawn.h>
+#endif
+#include <glib/gstrfuncs.h>
+#include <glib/gstring.h>
+#if 0
+#include <glib/gthread.h>
+#include <glib/gthreadpool.h>
+#include <glib/gtimer.h>
+#include <glib/gtree.h>
+#endif
+#include <glib/gtypes.h>
+#if 0
+#include <glib/gunicode.h>
+#include <glib/gutils.h>
+#ifdef G_PLATFORM_WIN32
+#include <glib/gwin32.h>
+#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 <glib/gtypes.h>
+
+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 <glib/gmem.h>
+#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 <stdio.h>
+
+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 <glib/gtypes.h>
+
+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 <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include <errno.h>
+#include <ctype.h> /* For tolower() */
+#if !defined (HAVE_STRSIGNAL) || !defined(NO_SYS_SIGLIST_DECL)
+#include <signal.h>
+#endif
+
+#include "glib.h"
+#if 0
+#include "gprintf.h"
+#include "gprintfint.h"
+
+#include "galias.h"
+
+#ifdef G_OS_WIN32
+#include <windows.h>
+#endif
+#endif
+
+/* do not include <unistd.h> 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 <Todd.Miller@courtesan.com> 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 &lt; @s2,
+ * or a positive value if @s1 &gt; @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 &lt; @s2,
+ * or a positive value if @s1 &gt; @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 &lt; @s2,
+ * or a positive value if @s1 &gt; @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 &lt; @s2,
+ * or a positive value if @s1 &gt; @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 <stdarg.h>
+#include <glib/gtypes.h>
+
+G_BEGIN_DECLS
+
+/* Functions like the ones in <ctype.h> 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 <unistd.h>
+#endif
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#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 <glib/gtypes.h>
+#if 0
+#include <glib/gunicode.h>
+#include <glib/gutils.h> /* 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 <glibconfig.h>
+
+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 <stddef.h>
+#include <sys/types.h>
+#include <stdint.h>
+
+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 <glib/macros.h> ================ */
+
+#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 <glib/gmem.h> ====================== */
+
+#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 <glib/gmessages.h> =================== */
+
+#include <stdlib.h>
+
+#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 <glib/gprintf.h> ==================== */
+
+#include <stdio.h>
+
+#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 <glib/gslice.h> ===================== */
+
+#define g_slice_new(t) XMALLOC (t)
+#define g_slice_new0(t) XZALLOC (t)
+
+#define g_slice_free(t,p) free (p)
+
+/* ======================= Helper for <glib/gtypes.h> ======================= */
+
+/* We don't need to export variables from a shared library. */
+#define GLIB_VAR extern
+
+/* ==================== Substitute for <glib/gunicode.h> ==================== */
+
+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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2005.
+ Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h,
+ gthr-win32.h. */
+
+#include <config.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 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 <errno.h>
+#include <stdlib.h>
+
+/* ========================================================================= */
+
+#if USE_POSIX_THREADS
+
+/* Use the POSIX threads library. */
+
+# include <pthread.h>
+
+# 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 <pth.h>
+
+# 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 <thread.h>
+# include <synch.h>
+
+# 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 <windows.h>
+
+# 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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2005. */
+
+#include <config.h>
+
+/* ========================================================================= */
+
+#if USE_POSIX_THREADS
+
+/* Use the POSIX threads library. */
+
+# include <pthread.h>
+# include <stdlib.h>
+
+# 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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2005. */
+
+#include <config.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 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 <errno.h>
+#include <stdlib.h>
+
+/* ========================================================================= */
+
+#if USE_POSIX_THREADS
+
+/* Use the POSIX threads library. */
+
+# include <pthread.h>
+
+# 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 <pth.h>
+
+# 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 <thread.h>
+
+# 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 <windows.h>
+
+/* ------------------------- 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 <drepper@gnu.ai.mit.edu>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "hash.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <limits.h>
+#include <sys/types.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "html-ostream.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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, "<span class=\"");
+ ostream_write_str (stream->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, "</span>");
+ 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, "<br/>");
+ stream->curr_class_stack_size = prev_class_stack_size;
+ }
+ else
+ {
+ emit_pending_spans (stream, true);
+
+ switch (uc)
+ {
+ case '"':
+ ostream_write_str (stream->destination, "&quot;");
+ break;
+ case '&':
+ ostream_write_str (stream->destination, "&amp;");
+ break;
+ case '<':
+ ostream_write_str (stream->destination, "&lt;");
+ break;
+ case '>':
+ /* Needed to avoid "]]>" in the output. */
+ ostream_write_str (stream->destination, "&gt;");
+ break;
+ case ' ':
+ /* Needed because HTML viewers merge adjacent spaces
+ and drop spaces adjacent to <br> and similar. */
+ ostream_write_str (stream->destination, "&nbsp;");
+ 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#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 <body><html> 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "html-ostream.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 /* <char *> */ 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, "<span class=\"");
+ ostream_write_str (stream->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, "</span>");
+ 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, "<br/>");
+ stream->curr_class_stack_size = prev_class_stack_size;
+ }
+ else
+ {
+ emit_pending_spans (stream, true);
+
+ switch (uc)
+ {
+ case '"':
+ ostream_write_str (stream->destination, "&quot;");
+ break;
+ case '&':
+ ostream_write_str (stream->destination, "&amp;");
+ break;
+ case '<':
+ ostream_write_str (stream->destination, "&lt;");
+ break;
+ case '>':
+ /* Needed to avoid "]]>" in the output. */
+ ostream_write_str (stream->destination, "&gt;");
+ break;
+ case ' ':
+ /* Needed because HTML viewers merge adjacent spaces
+ and drop spaces adjacent to <br> and similar. */
+ ostream_write_str (stream->destination, "&nbsp;");
+ 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _HTML_OSTREAM_H
+#define _HTML_OSTREAM_H
+
+#include "ostream.h"
+
+
+struct html_ostream : struct ostream
+{
+methods:
+
+ /* Start a <span class="CLASSNAME"> 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 <span class="CLASSNAME"> 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 <body><html> 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "html-styled-ostream.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#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, "</body>\n");
+ ostream_write_str (stream->destination, "</html>\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, "<?xml version=\"1.0\"?>\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 <br/> or <p></p>,
+ - every attribute specification is in assignment form, like
+ <table border="1">,
+ - every <a name="..."> element also has an 'id' attribute,
+ - special characters like < > & " are escaped in the <style> and
+ <script> elements. */
+ ostream_write_str (stream->destination,
+ "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n");
+ ostream_write_str (stream->destination, "<html>\n");
+ ostream_write_str (stream->destination, "<head>\n");
+ if (css_filename != NULL)
+ {
+ ostream_write_str (stream->destination, "<style type=\"text/css\">\n"
+ "<!--\n");
+
+ /* Include the contents of CSS_FILENAME literally. */
+ {
+ int fd;
+ char buf[4096];
+
+ fd = open (css_filename, O_RDONLY | O_TEXT);
+ if (fd < 0)
+ error (EXIT_FAILURE, errno,
+ _("error while opening \"%s\" for reading"),
+ css_filename);
+
+ for (;;)
+ {
+ size_t n_read = safe_read (fd, buf, sizeof (buf));
+ if (n_read == SAFE_READ_ERROR)
+ error (EXIT_FAILURE, errno, _("error reading \"%s\""),
+ css_filename);
+ if (n_read == 0)
+ break;
+
+ ostream_write_mem (stream->destination, buf, n_read);
+ }
+
+ if (close (fd) < 0)
+ error (EXIT_FAILURE, errno, _("error after reading \"%s\""),
+ css_filename);
+ }
+
+ ostream_write_str (stream->destination, "-->\n"
+ "</style>\n");
+ }
+ ostream_write_str (stream->destination, "</head>\n");
+ ostream_write_str (stream->destination, "<body>\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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "html-styled-ostream.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#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, "</body>\n");
+ ostream_write_str (stream->destination, "</html>\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, "<?xml version=\"1.0\"?>\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 <br/> or <p></p>,
+ - every attribute specification is in assignment form, like
+ <table border="1">,
+ - every <a name="..."> element also has an 'id' attribute,
+ - special characters like < > & " are escaped in the <style> and
+ <script> elements. */
+ ostream_write_str (stream->destination,
+ "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n");
+ ostream_write_str (stream->destination, "<html>\n");
+ ostream_write_str (stream->destination, "<head>\n");
+ if (css_filename != NULL)
+ {
+ ostream_write_str (stream->destination, "<style type=\"text/css\">\n"
+ "<!--\n");
+
+ /* Include the contents of CSS_FILENAME literally. */
+ {
+ int fd;
+ char buf[4096];
+
+ fd = open (css_filename, O_RDONLY | O_TEXT);
+ if (fd < 0)
+ error (EXIT_FAILURE, errno,
+ _("error while opening \"%s\" for reading"),
+ css_filename);
+
+ for (;;)
+ {
+ size_t n_read = safe_read (fd, buf, sizeof (buf));
+ if (n_read == SAFE_READ_ERROR)
+ error (EXIT_FAILURE, errno, _("error reading \"%s\""),
+ css_filename);
+ if (n_read == 0)
+ break;
+
+ ostream_write_mem (stream->destination, buf, n_read);
+ }
+
+ if (close (fd) < 0)
+ error (EXIT_FAILURE, errno, _("error after reading \"%s\""),
+ css_filename);
+ }
+
+ ostream_write_str (stream->destination, "-->\n"
+ "</style>\n");
+ }
+ ostream_write_str (stream->destination, "</head>\n");
+ ostream_write_str (stream->destination, "<body>\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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <iconv.h>
+
+#include <stddef.h>
+
+#if REPLACE_ICONV_UTF
+# include <errno.h>
+# include <stdint.h>
+# include <stdlib.h>
+# 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 <iconv.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 <http://www.gnu.org/licenses/>. */
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <iconv.h>
+
+#include <stdint.h>
+#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 <bug-gnu-gperf@gnu.org>."
+#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 <bug-gnu-gperf@gnu.org>."
+#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 <bug-gnu-gperf@gnu.org>."
+#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 <bug-gnu-gperf@gnu.org>."
+#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 <bug-gnu-gperf@gnu.org>."
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <iconv.h>
+
+#include <errno.h>
+#include <string.h>
+#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 <http://www.gnu.org/licenses/>. */
+
+#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 <http://www.gnu.org/licenses/>. */
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert. */
+
+#ifndef _GL_INTPROPS_H
+#define _GL_INTPROPS_H
+
+#include <limits.h>
+
+/* 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
+ <http://lists.gnu.org/archive/html/bug-gnulib/2011-05/msg00406.html>. */
+#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_<op>_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_<op>_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
+ <http://lists.gnu.org/archive/html/bug-gnulib/2011-05/msg00401.html>. */
+#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_<op>_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 <op> 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <wctype.h>
+
+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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <float.h>
+
+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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+#include <alloca.h>
+
+/* Specification. */
+#include "javacomp.h"
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#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> { 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> { 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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _JAVACOMP_H
+#define _JAVACOMP_H
+
+#include <stdbool.h>
+
+/* 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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+#include <alloca.h>
+
+/* Specification. */
+#include "javaexec.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _JAVAEXEC_H
+#define _JAVAEXEC_H
+
+#include <stdbool.h>
+
+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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "javaversion.h"
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+#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
--- /dev/null
+++ b/gettext-tools/gnulib-lib/javaversion.class
Binary files 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#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 <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * 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 <config.h>
+#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 <stdio.h>
+#include <glib.h>
+#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 <config.h>
+#include <stdio.h>
+#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 <stdio.h>
+#include <glib.h>
+#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 <dodji@seketeli.org>
+ *
+ * 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 <config.h>
+#include <string.h>
+#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 <config.h>
+#include <string.h>
+#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 <stdio.h>
+#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 <config.h>
+#include <string.h>
+#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 <glib.h>
+#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 <dodji@seketeli.org>
+ *
+ * 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 <config.h>
+#include "cr-enc-handler.h"
+#include "cr-utils.h"
+
+#include <string.h>
+
+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 <dodji@seketeli.org>
+ *
+ * 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 <config.h>
+#include "cr-fonts.h"
+#include <string.h>
+
+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 <config.h>
+#include "stdio.h"
+#include <string.h>
+#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 <glib.h>
+#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 <config.h>
+#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 <glib.h>
+#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 <config.h>
+#include <string.h>
+#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 <dodji@seketeli.org>
+ *
+ * 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 <config.h>
+#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_<production_name> (...) ;
+ *where <production_name> 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_<production_name> (...) ;
+ *Then css core grammar related parsing function will be called:
+ *cr_parser_parse_<production_name>_core (...) ;
+ *
+ *If a production is defined only by the css core grammar, then
+ *it will be named:
+ *cr_parser_parse_<production_name>_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,
+ &param);
+
+ 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 <glib.h>
+#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 <config.h>
+#include <string.h>
+#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 <config.h>
+#include <string.h>
+#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 <config.h>
+#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 <stdio.h>
+#include <glib.h>
+#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 <config.h>
+#include <stdio.h>
+#include <string.h>
+#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 <stdio.h>
+#include <glib.h>
+#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 <config.h>
+#include <string.h>
+#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 <libxml/tree.h>
+#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 <config.h>
+#include <string.h>
+#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 <stdio.h>
+#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 <config.h>
+#include <string.h>
+#include <glib.h>
+#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 <stdio.h>
+#include <glib.h>
+#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 <config.h>
+#include <string.h>
+#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 <stdio.h>
+#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 <config.h>
+#include <string.h>
+#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 <glib.h>
+#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 <config.h>
+#include <string.h>
+#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 <config.h>
+#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 <config.h>
+#include <stdio.h>
+#include <string.h>
+#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 <stdio.h>
+#include <glib.h>
+#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 <config.h>
+#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 <config.h>
+#include <string.h>
+#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 <config.h>
+#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 <stdio.h>
+#include <glib.h>
+#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 <dodji@seketeli.org>
+ *
+ * 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 <libxml/xmlerror.h>
+#include <libxml/DOCBparser.h>
+
+/**
+ * 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 <libxml/xmlversion.h>
+
+#ifdef LIBXML_DOCB_ENABLED
+
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+
+#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 <string.h>
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_ZLIB_H
+#include <zlib.h>
+#endif
+
+#include <libxml/xmlmemory.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/xmlerror.h>
+#include <libxml/HTMLparser.h>
+#include <libxml/HTMLtree.h>
+#include <libxml/entities.h>
+#include <libxml/encoding.h>
+#include <libxml/valid.h>
+#include <libxml/xmlIO.h>
+#include <libxml/globals.h>
+#include <libxml/uri.h>
+
+#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 ...<b> </b>...
+ 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 <p><b>xy</b> <i>z</i><p>
+ 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 "</" within the content.
+ * Escape mechanisms are specific to each scripting or
+ * style sheet language.
+ *
+ * In recovery mode, only break if end tag match the
+ * current tag, effectively ignoring all tags inside the
+ * script/style block and treating the entire block as
+ * CDATA.
+ */
+ if (ctxt->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 ::= '<?' PITarget (S (Char* - (Char* '?>' 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 ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
+ */
+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<!--%.50s\n", buf, NULL);
+ xmlFree(buf);
+ } else {
+ NEXT;
+ if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
+ (!ctxt->disableSAX))
+ ctxt->sax->comment(ctxt->userData, buf);
+ xmlFree(buf);
+ }
+ ctxt->instate = state;
+}
+
+/**
+ * htmlParseCharRef:
+ * @ctxt: an HTML parser context
+ *
+ * parse Reference declarations
+ *
+ * [66] CharRef ::= '&#' [0-9]+ ';' |
+ * '&#x' [0-9a-fA-F]+ ';'
+ *
+ * Returns the value parsed (as an int)
+ */
+int
+htmlParseCharRef(htmlParserCtxtPtr ctxt) {
+ int val = 0;
+
+ if ((ctxt == NULL) || (ctxt->input == NULL)) {
+ htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
+ "htmlParseCharRef: context error\n",
+ NULL, NULL);
+ return(0);
+ }
+ if ((CUR == '&') && (NXT(1) == '#') &&
+ ((NXT(2) == 'x') || NXT(2) == 'X')) {
+ SKIP(3);
+ while (CUR != ';') {
+ 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 {
+ htmlParseErr(ctxt, XML_ERR_INVALID_HEX_CHARREF,
+ "htmlParseCharRef: invalid hexadecimal value\n",
+ NULL, NULL);
+ return(0);
+ }
+ NEXT;
+ }
+ if (CUR == ';')
+ NEXT;
+ } else if ((CUR == '&') && (NXT(1) == '#')) {
+ SKIP(2);
+ while (CUR != ';') {
+ if ((CUR >= '0') && (CUR <= '9'))
+ val = val * 10 + (CUR - '0');
+ else {
+ htmlParseErr(ctxt, XML_ERR_INVALID_DEC_CHARREF,
+ "htmlParseCharRef: invalid decimal value\n",
+ NULL, NULL);
+ return(0);
+ }
+ NEXT;
+ }
+ if (CUR == ';')
+ NEXT;
+ } else {
+ htmlParseErr(ctxt, XML_ERR_INVALID_CHARREF,
+ "htmlParseCharRef: invalid value\n", NULL, NULL);
+ }
+ /*
+ * Check the value IS_CHAR ...
+ */
+ if (IS_CHAR(val)) {
+ return(val);
+ } else {
+ htmlParseErrInt(ctxt, XML_ERR_INVALID_CHAR,
+ "htmlParseCharRef: invalid xmlChar value %d\n",
+ val);
+ }
+ return(0);
+}
+
+
+/**
+ * htmlParseDocTypeDecl:
+ * @ctxt: an HTML parser context
+ *
+ * parse a DOCTYPE declaration
+ *
+ * [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S?
+ * ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
+ */
+
+static void
+htmlParseDocTypeDecl(htmlParserCtxtPtr ctxt) {
+ const xmlChar *name;
+ xmlChar *ExternalID = NULL;
+ xmlChar *URI = NULL;
+
+ /*
+ * We know that '<!DOCTYPE' has been detected.
+ */
+ SKIP(9);
+
+ SKIP_BLANKS;
+
+ /*
+ * Parse the DOCTYPE name.
+ */
+ name = htmlParseName(ctxt);
+ if (name == NULL) {
+ htmlParseErr(ctxt, XML_ERR_NAME_REQUIRED,
+ "htmlParseDocTypeDecl : no DOCTYPE name !\n",
+ NULL, NULL);
+ }
+ /*
+ * Check that upper(name) == "HTML" !!!!!!!!!!!!!
+ */
+
+ SKIP_BLANKS;
+
+ /*
+ * Check for SystemID and ExternalID
+ */
+ URI = htmlParseExternalID(ctxt, &ExternalID);
+ SKIP_BLANKS;
+
+ /*
+ * We should be at the end of the DOCTYPE declaration.
+ */
+ if (CUR != '>') {
+ htmlParseErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED,
+ "DOCTYPE improperly terminated\n", NULL, NULL);
+ /* We shouldn't try to resynchronize ... */
+ }
+ NEXT;
+
+ /*
+ * Create or update the document accordingly to the DOCTYPE
+ */
+ if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL) &&
+ (!ctxt->disableSAX))
+ ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI);
+
+ /*
+ * Cleanup, since we don't use all those identifiers
+ */
+ if (URI != NULL) xmlFree(URI);
+ if (ExternalID != NULL) xmlFree(ExternalID);
+}
+
+/**
+ * htmlParseAttribute:
+ * @ctxt: an HTML parser context
+ * @value: a xmlChar ** used to store the value of the attribute
+ *
+ * parse an attribute
+ *
+ * [41] Attribute ::= Name Eq AttValue
+ *
+ * [25] Eq ::= S? '=' S?
+ *
+ * With namespace:
+ *
+ * [NS 11] Attribute ::= QName Eq AttValue
+ *
+ * Also the case QName == xmlns:??? is handled independently as a namespace
+ * definition.
+ *
+ * Returns the attribute name, and the value in *value.
+ */
+
+static const xmlChar *
+htmlParseAttribute(htmlParserCtxtPtr ctxt, xmlChar **value) {
+ const xmlChar *name;
+ xmlChar *val = NULL;
+
+ *value = NULL;
+ name = htmlParseHTMLName(ctxt);
+ if (name == NULL) {
+ htmlParseErr(ctxt, XML_ERR_NAME_REQUIRED,
+ "error parsing attribute name\n", NULL, NULL);
+ return(NULL);
+ }
+
+ /*
+ * read the value
+ */
+ SKIP_BLANKS;
+ if (CUR == '=') {
+ NEXT;
+ SKIP_BLANKS;
+ val = htmlParseAttValue(ctxt);
+ } else if (htmlIsBooleanAttr(name)) {
+ /*
+ * assume a minimized attribute
+ */
+ val = xmlStrdup(name);
+ }
+
+ *value = val;
+ return(name);
+}
+
+/**
+ * htmlCheckEncoding:
+ * @ctxt: an HTML parser context
+ * @attvalue: the attribute value
+ *
+ * Checks an http-equiv attribute from a Meta tag to detect
+ * the encoding
+ * If a new encoding is detected the parser is switched to decode
+ * it and pass UTF8
+ */
+static void
+htmlCheckEncoding(htmlParserCtxtPtr ctxt, const xmlChar *attvalue) {
+ const xmlChar *encoding;
+
+ if ((ctxt == NULL) || (attvalue == NULL))
+ return;
+
+ /* do not change encoding */
+ if (ctxt->input->encoding != NULL)
+ return;
+
+ encoding = xmlStrcasestr(attvalue, BAD_CAST"charset=");
+ if (encoding != NULL) {
+ encoding += 8;
+ } else {
+ encoding = xmlStrcasestr(attvalue, BAD_CAST"charset =");
+ if (encoding != NULL)
+ encoding += 9;
+ }
+ if (encoding != NULL) {
+ xmlCharEncoding enc;
+ xmlCharEncodingHandlerPtr handler;
+
+ while ((*encoding == ' ') || (*encoding == '\t')) encoding++;
+
+ if (ctxt->input->encoding != NULL)
+ xmlFree((xmlChar *) ctxt->input->encoding);
+ ctxt->input->encoding = xmlStrdup(encoding);
+
+ enc = xmlParseCharEncoding((const char *) encoding);
+ /*
+ * registered set of known encodings
+ */
+ if (enc != XML_CHAR_ENCODING_ERROR) {
+ if (((enc == XML_CHAR_ENCODING_UTF16LE) ||
+ (enc == XML_CHAR_ENCODING_UTF16BE) ||
+ (enc == XML_CHAR_ENCODING_UCS4LE) ||
+ (enc == XML_CHAR_ENCODING_UCS4BE)) &&
+ (ctxt->input->buf != NULL) &&
+ (ctxt->input->buf->encoder == NULL)) {
+ htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING,
+ "htmlCheckEncoding: wrong encoding meta\n",
+ NULL, NULL);
+ } else {
+ xmlSwitchEncoding(ctxt, enc);
+ }
+ ctxt->charset = XML_CHAR_ENCODING_UTF8;
+ } else {
+ /*
+ * fallback for unknown encodings
+ */
+ handler = xmlFindCharEncodingHandler((const char *) encoding);
+ if (handler != NULL) {
+ xmlSwitchToEncoding(ctxt, handler);
+ ctxt->charset = XML_CHAR_ENCODING_UTF8;
+ } else {
+ ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
+ }
+ }
+
+ if ((ctxt->input->buf != NULL) &&
+ (ctxt->input->buf->encoder != NULL) &&
+ (ctxt->input->buf->raw != NULL) &&
+ (ctxt->input->buf->buffer != NULL)) {
+ int nbchars;
+ int processed;
+
+ /*
+ * convert as much as possible to the parser reading buffer.
+ */
+ processed = ctxt->input->cur - ctxt->input->base;
+ xmlBufferShrink(ctxt->input->buf->buffer, processed);
+ nbchars = xmlCharEncInFunc(ctxt->input->buf->encoder,
+ ctxt->input->buf->buffer,
+ ctxt->input->buf->raw);
+ if (nbchars < 0) {
+ htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING,
+ "htmlCheckEncoding: encoder error\n",
+ NULL, NULL);
+ }
+ ctxt->input->base =
+ ctxt->input->cur = ctxt->input->buf->buffer->content;
+ }
+ }
+}
+
+/**
+ * htmlCheckMeta:
+ * @ctxt: an HTML parser context
+ * @atts: the attributes values
+ *
+ * Checks an attributes from a Meta tag
+ */
+static void
+htmlCheckMeta(htmlParserCtxtPtr ctxt, const xmlChar **atts) {
+ int i;
+ const xmlChar *att, *value;
+ int http = 0;
+ const xmlChar *content = NULL;
+
+ if ((ctxt == NULL) || (atts == NULL))
+ return;
+
+ i = 0;
+ att = atts[i++];
+ while (att != NULL) {
+ value = atts[i++];
+ if ((value != NULL) && (!xmlStrcasecmp(att, BAD_CAST"http-equiv"))
+ && (!xmlStrcasecmp(value, BAD_CAST"Content-Type")))
+ http = 1;
+ else if ((value != NULL) && (!xmlStrcasecmp(att, BAD_CAST"content")))
+ content = value;
+ att = atts[i++];
+ }
+ if ((http) && (content != NULL))
+ htmlCheckEncoding(ctxt, content);
+
+}
+
+/**
+ * htmlParseStartTag:
+ * @ctxt: an HTML parser context
+ *
+ * parse a start of tag either for rule element or
+ * EmptyElement. In both case we don't parse the tag closing chars.
+ *
+ * [40] STag ::= '<' Name (S Attribute)* S? '>'
+ *
+ * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
+ *
+ * With namespace:
+ *
+ * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
+ *
+ * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
+ *
+ * Returns 0 in case of success and -1 in case of error.
+ */
+
+static int
+htmlParseStartTag(htmlParserCtxtPtr ctxt) {
+ const xmlChar *name;
+ const xmlChar *attname;
+ xmlChar *attvalue;
+ const xmlChar **atts;
+ int nbatts = 0;
+ int maxatts;
+ int meta = 0;
+ int i;
+
+ if ((ctxt == NULL) || (ctxt->input == NULL)) {
+ htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
+ "htmlParseStartTag: context error\n", NULL, NULL);
+ return -1;
+ }
+ if (CUR != '<') return -1;
+ NEXT;
+
+ atts = ctxt->atts;
+ maxatts = ctxt->maxatts;
+
+ GROW;
+ name = htmlParseHTMLName(ctxt);
+ if (name == NULL) {
+ htmlParseErr(ctxt, XML_ERR_NAME_REQUIRED,
+ "htmlParseStartTag: invalid element name\n",
+ NULL, NULL);
+ /* Dump the bogus tag like browsers do */
+ while ((IS_CHAR_CH(CUR)) && (CUR != '>'))
+ NEXT;
+ return -1;
+ }
+ if (xmlStrEqual(name, BAD_CAST"meta"))
+ meta = 1;
+
+ /*
+ * Check for auto-closure of HTML elements.
+ */
+ htmlAutoClose(ctxt, name);
+
+ /*
+ * Check for implied HTML elements.
+ */
+ htmlCheckImplied(ctxt, name);
+
+ /*
+ * Avoid html at any level > 0, head at any level != 1
+ * or any attempt to recurse body
+ */
+ if ((ctxt->nameNr > 0) && (xmlStrEqual(name, BAD_CAST"html"))) {
+ htmlParseErr(ctxt, XML_HTML_STRUCURE_ERROR,
+ "htmlParseStartTag: misplaced <html> tag\n",
+ name, NULL);
+ return 0;
+ }
+ if ((ctxt->nameNr != 1) &&
+ (xmlStrEqual(name, BAD_CAST"head"))) {
+ htmlParseErr(ctxt, XML_HTML_STRUCURE_ERROR,
+ "htmlParseStartTag: misplaced <head> tag\n",
+ name, NULL);
+ return 0;
+ }
+ if (xmlStrEqual(name, BAD_CAST"body")) {
+ int indx;
+ for (indx = 0;indx < ctxt->nameNr;indx++) {
+ if (xmlStrEqual(ctxt->nameTab[indx], BAD_CAST"body")) {
+ htmlParseErr(ctxt, XML_HTML_STRUCURE_ERROR,
+ "htmlParseStartTag: misplaced <body> tag\n",
+ name, NULL);
+ while ((IS_CHAR_CH(CUR)) && (CUR != '>'))
+ NEXT;
+ return 0;
+ }
+ }
+ }
+
+ /*
+ * Now parse the attributes, it ends up with the ending
+ *
+ * (S Attribute)* S?
+ */
+ SKIP_BLANKS;
+ while ((IS_CHAR_CH(CUR)) &&
+ (CUR != '>') &&
+ ((CUR != '/') || (NXT(1) != '>'))) {
+ long cons = ctxt->nbChars;
+
+ GROW;
+ attname = htmlParseAttribute(ctxt, &attvalue);
+ if (attname != NULL) {
+
+ /*
+ * Well formedness requires at most one declaration of an attribute
+ */
+ for (i = 0; i < nbatts;i += 2) {
+ if (xmlStrEqual(atts[i], attname)) {
+ htmlParseErr(ctxt, XML_ERR_ATTRIBUTE_REDEFINED,
+ "Attribute %s redefined\n", attname, NULL);
+ if (attvalue != NULL)
+ xmlFree(attvalue);
+ goto failed;
+ }
+ }
+
+ /*
+ * Add the pair to atts
+ */
+ if (atts == NULL) {
+ maxatts = 22; /* allow for 10 attrs by default */
+ atts = (const xmlChar **)
+ xmlMalloc(maxatts * sizeof(xmlChar *));
+ if (atts == NULL) {
+ htmlErrMemory(ctxt, NULL);
+ if (attvalue != NULL)
+ xmlFree(attvalue);
+ goto failed;
+ }
+ ctxt->atts = atts;
+ ctxt->maxatts = maxatts;
+ } else if (nbatts + 4 > maxatts) {
+ const xmlChar **n;
+
+ maxatts *= 2;
+ n = (const xmlChar **) xmlRealloc((void *) atts,
+ maxatts * sizeof(const xmlChar *));
+ if (n == NULL) {
+ htmlErrMemory(ctxt, NULL);
+ if (attvalue != NULL)
+ xmlFree(attvalue);
+ goto failed;
+ }
+ atts = n;
+ ctxt->atts = atts;
+ ctxt->maxatts = maxatts;
+ }
+ atts[nbatts++] = attname;
+ atts[nbatts++] = attvalue;
+ atts[nbatts] = NULL;
+ atts[nbatts + 1] = NULL;
+ }
+ else {
+ if (attvalue != NULL)
+ xmlFree(attvalue);
+ /* Dump the bogus attribute string up to the next blank or
+ * the end of the tag. */
+ while ((IS_CHAR_CH(CUR)) &&
+ !(IS_BLANK_CH(CUR)) && (CUR != '>') &&
+ ((CUR != '/') || (NXT(1) != '>')))
+ NEXT;
+ }
+
+failed:
+ SKIP_BLANKS;
+ if (cons == ctxt->nbChars) {
+ htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
+ "htmlParseStartTag: problem parsing attributes\n",
+ NULL, NULL);
+ break;
+ }
+ }
+
+ /*
+ * Handle specific association to the META tag
+ */
+ if (meta)
+ htmlCheckMeta(ctxt, atts);
+
+ /*
+ * SAX: Start of Element !
+ */
+ htmlnamePush(ctxt, name);
+ if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL)) {
+ if (nbatts != 0)
+ ctxt->sax->startElement(ctxt->userData, name, atts);
+ else
+ ctxt->sax->startElement(ctxt->userData, name, NULL);
+ }
+
+ if (atts != NULL) {
+ for (i = 1;i < nbatts;i += 2) {
+ if (atts[i] != NULL)
+ xmlFree((xmlChar *) atts[i]);
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * htmlParseEndTag:
+ * @ctxt: an HTML parser context
+ *
+ * parse an end of tag
+ *
+ * [42] ETag ::= '</' Name S? '>'
+ *
+ * With namespace
+ *
+ * [NS 9] ETag ::= '</' QName S? '>'
+ *
+ * Returns 1 if the current level should be closed.
+ */
+
+static int
+htmlParseEndTag(htmlParserCtxtPtr ctxt)
+{
+ const xmlChar *name;
+ const xmlChar *oldname;
+ int i, ret;
+
+ if ((CUR != '<') || (NXT(1) != '/')) {
+ htmlParseErr(ctxt, XML_ERR_LTSLASH_REQUIRED,
+ "htmlParseEndTag: '</' not found\n", NULL, NULL);
+ return (0);
+ }
+ SKIP(2);
+
+ name = htmlParseHTMLName(ctxt);
+ if (name == NULL)
+ return (0);
+
+ /*
+ * We should definitely be at the ending "S? '>'" part
+ */
+ SKIP_BLANKS;
+ if ((!IS_CHAR_CH(CUR)) || (CUR != '>')) {
+ htmlParseErr(ctxt, XML_ERR_GT_REQUIRED,
+ "End tag : expected '>'\n", NULL, NULL);
+ if (ctxt->recovery) {
+ /*
+ * We're not at the ending > !!
+ * Error, unless in recover mode where we search forwards
+ * until we find a >
+ */
+ while (CUR != '\0' && CUR != '>') NEXT;
+ NEXT;
+ }
+ } else
+ NEXT;
+
+ /*
+ * If the name read is not one of the element in the parsing stack
+ * then return, it's just an error.
+ */
+ for (i = (ctxt->nameNr - 1); i >= 0; i--) {
+ if (xmlStrEqual(name, ctxt->nameTab[i]))
+ break;
+ }
+ if (i < 0) {
+ htmlParseErr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
+ "Unexpected end tag : %s\n", name, NULL);
+ return (0);
+ }
+
+
+ /*
+ * Check for auto-closure of HTML elements.
+ */
+
+ htmlAutoCloseOnClose(ctxt, name);
+
+ /*
+ * Well formedness constraints, opening and closing must match.
+ * With the exception that the autoclose may have popped stuff out
+ * of the stack.
+ */
+ if (!xmlStrEqual(name, ctxt->name)) {
+ if ((ctxt->name != NULL) && (!xmlStrEqual(ctxt->name, name))) {
+ htmlParseErr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
+ "Opening and ending tag mismatch: %s and %s\n",
+ name, ctxt->name);
+ }
+ }
+
+ /*
+ * SAX: End of Tag
+ */
+ oldname = ctxt->name;
+ if ((oldname != NULL) && (xmlStrEqual(oldname, name))) {
+ if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
+ ctxt->sax->endElement(ctxt->userData, name);
+ htmlnamePop(ctxt);
+ ret = 1;
+ } else {
+ ret = 0;
+ }
+
+ return (ret);
+}
+
+
+/**
+ * htmlParseReference:
+ * @ctxt: an HTML parser context
+ *
+ * parse and handle entity references in content,
+ * this will end-up in a call to character() since this is either a
+ * CharRef, or a predefined entity.
+ */
+static void
+htmlParseReference(htmlParserCtxtPtr ctxt) {
+ const htmlEntityDesc * ent;
+ xmlChar out[6];
+ const xmlChar *name;
+ if (CUR != '&') return;
+
+ if (NXT(1) == '#') {
+ unsigned int c;
+ int bits, i = 0;
+
+ c = htmlParseCharRef(ctxt);
+ if (c == 0)
+ return;
+
+ if (c < 0x80) { out[i++]= c; bits= -6; }
+ else if (c < 0x800) { out[i++]=((c >> 6) & 0x1F) | 0xC0; bits= 0; }
+ else if (c < 0x10000) { out[i++]=((c >> 12) & 0x0F) | 0xE0; bits= 6; }
+ else { out[i++]=((c >> 18) & 0x07) | 0xF0; bits= 12; }
+
+ for ( ; bits >= 0; bits-= 6) {
+ out[i++]= ((c >> bits) & 0x3F) | 0x80;
+ }
+ out[i] = 0;
+
+ htmlCheckParagraph(ctxt);
+ if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
+ ctxt->sax->characters(ctxt->userData, out, i);
+ } else {
+ ent = htmlParseEntityRef(ctxt, &name);
+ if (name == NULL) {
+ htmlCheckParagraph(ctxt);
+ if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
+ ctxt->sax->characters(ctxt->userData, BAD_CAST "&", 1);
+ return;
+ }
+ if ((ent == NULL) || !(ent->value > 0)) {
+ htmlCheckParagraph(ctxt);
+ if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL)) {
+ ctxt->sax->characters(ctxt->userData, BAD_CAST "&", 1);
+ ctxt->sax->characters(ctxt->userData, name, xmlStrlen(name));
+ /* ctxt->sax->characters(ctxt->userData, BAD_CAST ";", 1); */
+ }
+ } else {
+ unsigned int c;
+ int bits, i = 0;
+
+ c = ent->value;
+ if (c < 0x80)
+ { out[i++]= c; bits= -6; }
+ else if (c < 0x800)
+ { out[i++]=((c >> 6) & 0x1F) | 0xC0; bits= 0; }
+ else if (c < 0x10000)
+ { out[i++]=((c >> 12) & 0x0F) | 0xE0; bits= 6; }
+ else
+ { out[i++]=((c >> 18) & 0x07) | 0xF0; bits= 12; }
+
+ for ( ; bits >= 0; bits-= 6) {
+ out[i++]= ((c >> bits) & 0x3F) | 0x80;
+ }
+ out[i] = 0;
+
+ htmlCheckParagraph(ctxt);
+ if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
+ ctxt->sax->characters(ctxt->userData, out, i);
+ }
+ }
+}
+
+/**
+ * htmlParseContent:
+ * @ctxt: an HTML parser context
+ *
+ * Parse a content: comment, sub-element, reference or text.
+ */
+
+static void
+htmlParseContent(htmlParserCtxtPtr ctxt) {
+ xmlChar *currentNode;
+ int depth;
+
+ currentNode = xmlStrdup(ctxt->name);
+ depth = ctxt->nameNr;
+ while (1) {
+ long cons = ctxt->nbChars;
+
+ GROW;
+ /*
+ * Our tag or one of it's parent or children is ending.
+ */
+ if ((CUR == '<') && (NXT(1) == '/')) {
+ if (htmlParseEndTag(ctxt) &&
+ ((currentNode != NULL) || (ctxt->nameNr == 0))) {
+ if (currentNode != NULL)
+ xmlFree(currentNode);
+ return;
+ }
+ continue; /* while */
+ }
+
+ /*
+ * Has this node been popped out during parsing of
+ * the next element
+ */
+ if ((ctxt->nameNr > 0) && (depth >= ctxt->nameNr) &&
+ (!xmlStrEqual(currentNode, ctxt->name)))
+ {
+ if (currentNode != NULL) xmlFree(currentNode);
+ return;
+ }
+
+ if ((CUR != 0) && ((xmlStrEqual(currentNode, BAD_CAST"script")) ||
+ (xmlStrEqual(currentNode, BAD_CAST"style")))) {
+ /*
+ * Handle SCRIPT/STYLE separately
+ */
+ htmlParseScript(ctxt);
+ } else {
+ /*
+ * Sometimes DOCTYPE arrives in the middle of the document
+ */
+ if ((CUR == '<') && (NXT(1) == '!') &&
+ (UPP(2) == 'D') && (UPP(3) == 'O') &&
+ (UPP(4) == 'C') && (UPP(5) == 'T') &&
+ (UPP(6) == 'Y') && (UPP(7) == 'P') &&
+ (UPP(8) == 'E')) {
+ htmlParseErr(ctxt, XML_HTML_STRUCURE_ERROR,
+ "Misplaced DOCTYPE declaration\n",
+ BAD_CAST "DOCTYPE" , NULL);
+ htmlParseDocTypeDecl(ctxt);
+ }
+
+ /*
+ * First case : a comment
+ */
+ if ((CUR == '<') && (NXT(1) == '!') &&
+ (NXT(2) == '-') && (NXT(3) == '-')) {
+ htmlParseComment(ctxt);
+ }
+
+ /*
+ * Second case : a Processing Instruction.
+ */
+ else if ((CUR == '<') && (NXT(1) == '?')) {
+ htmlParsePI(ctxt);
+ }
+
+ /*
+ * Third case : a sub-element.
+ */
+ else if (CUR == '<') {
+ htmlParseElement(ctxt);
+ }
+
+ /*
+ * Fourth case : a reference. If if has not been resolved,
+ * parsing returns it's Name, create the node
+ */
+ else if (CUR == '&') {
+ htmlParseReference(ctxt);
+ }
+
+ /*
+ * Fifth case : end of the resource
+ */
+ else if (CUR == 0) {
+ htmlAutoCloseOnEnd(ctxt);
+ break;
+ }
+
+ /*
+ * Last case, text. Note that References are handled directly.
+ */
+ else {
+ 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);
+ }
+ break;
+ }
+ }
+ GROW;
+ }
+ if (currentNode != NULL) xmlFree(currentNode);
+}
+
+/**
+ * htmlParseContent:
+ * @ctxt: an HTML parser context
+ *
+ * Parse a content: comment, sub-element, reference or text.
+ */
+
+void
+__htmlParseContent(void *ctxt) {
+ if (ctxt != NULL)
+ htmlParseContent((htmlParserCtxtPtr) ctxt);
+}
+
+/**
+ * htmlParseElement:
+ * @ctxt: an HTML parser context
+ *
+ * parse an HTML element, this is highly recursive
+ *
+ * [39] element ::= EmptyElemTag | STag content ETag
+ *
+ * [41] Attribute ::= Name Eq AttValue
+ */
+
+void
+htmlParseElement(htmlParserCtxtPtr ctxt) {
+ const xmlChar *name;
+ xmlChar *currentNode = NULL;
+ const htmlElemDesc * info;
+ htmlParserNodeInfo node_info;
+ int failed;
+ int depth;
+ const xmlChar *oldptr;
+
+ if ((ctxt == NULL) || (ctxt->input == NULL)) {
+ htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
+ "htmlParseElement: context error\n", NULL, NULL);
+ return;
+ }
+ /* Capture start position */
+ if (ctxt->record_info) {
+ node_info.begin_pos = ctxt->input->consumed +
+ (CUR_PTR - ctxt->input->base);
+ node_info.begin_line = ctxt->input->line;
+ }
+
+ failed = htmlParseStartTag(ctxt);
+ name = ctxt->name;
+ if (failed || (name == NULL)) {
+ if (CUR == '>')
+ NEXT;
+ return;
+ }
+
+ /*
+ * 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);
+ return;
+ }
+
+ 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);
+ }
+
+ /*
+ * Capture end position and add node
+ */
+ if (ctxt->record_info) {
+ node_info.end_pos = ctxt->input->consumed +
+ (CUR_PTR - ctxt->input->base);
+ node_info.end_line = ctxt->input->line;
+ node_info.node = ctxt->node;
+ xmlParserAddNodeInfo(ctxt, &node_info);
+ }
+ return;
+ }
+
+ /*
+ * 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);
+ return;
+ }
+
+ /*
+ * Parse the content of the element:
+ */
+ currentNode = xmlStrdup(ctxt->name);
+ depth = ctxt->nameNr;
+ while (IS_CHAR_CH(CUR)) {
+ oldptr = ctxt->input->cur;
+ htmlParseContent(ctxt);
+ if (oldptr==ctxt->input->cur) break;
+ if (ctxt->nameNr < depth) break;
+ }
+
+ /*
+ * Capture end position and add node
+ */
+ if ( currentNode != NULL && ctxt->record_info ) {
+ node_info.end_pos = ctxt->input->consumed +
+ (CUR_PTR - ctxt->input->base);
+ node_info.end_line = ctxt->input->line;
+ node_info.node = ctxt->node;
+ xmlParserAddNodeInfo(ctxt, &node_info);
+ }
+ if (!IS_CHAR_CH(CUR)) {
+ htmlAutoCloseOnEnd(ctxt);
+ }
+
+ if (currentNode != NULL)
+ xmlFree(currentNode);
+}
+
+/**
+ * htmlParseDocument:
+ * @ctxt: an HTML parser context
+ *
+ * parse an HTML 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
+htmlParseDocument(htmlParserCtxtPtr ctxt) {
+ xmlDtdPtr dtd;
+
+ xmlInitParser();
+
+ htmlDefaultSAXHandlerInit();
+
+ if ((ctxt == NULL) || (ctxt->input == NULL)) {
+ htmlParseErr(ctxt, XML_ERR_INTERNAL_ERROR,
+ "htmlParseDocument: context error\n", NULL, NULL);
+ return(XML_ERR_INTERNAL_ERROR);
+ }
+ ctxt->html = 1;
+ GROW;
+ /*
+ * SAX: beginning of the document processing.
+ */
+ if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
+ ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
+
+ /*
+ * Wipe out everything which is before the first '<'
+ */
+ SKIP_BLANKS;
+ if (CUR == 0) {
+ htmlParseErr(ctxt, XML_ERR_DOCUMENT_EMPTY,
+ "Document is empty\n", NULL, NULL);
+ }
+
+ if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
+ ctxt->sax->startDocument(ctxt->userData);
+
+
+ /*
+ * Parse possible comments and PIs before any content
+ */
+ while (((CUR == '<') && (NXT(1) == '!') &&
+ (NXT(2) == '-') && (NXT(3) == '-')) ||
+ ((CUR == '<') && (NXT(1) == '?'))) {
+ htmlParseComment(ctxt);
+ htmlParsePI(ctxt);
+ SKIP_BLANKS;
+ }
+
+
+ /*
+ * Then possibly doc type declaration(s) and more Misc
+ * (doctypedecl Misc*)?
+ */
+ if ((CUR == '<') && (NXT(1) == '!') &&
+ (UPP(2) == 'D') && (UPP(3) == 'O') &&
+ (UPP(4) == 'C') && (UPP(5) == 'T') &&
+ (UPP(6) == 'Y') && (UPP(7) == 'P') &&
+ (UPP(8) == 'E')) {
+ htmlParseDocTypeDecl(ctxt);
+ }
+ SKIP_BLANKS;
+
+ /*
+ * Parse possible comments and PIs before any content
+ */
+ while (((CUR == '<') && (NXT(1) == '!') &&
+ (NXT(2) == '-') && (NXT(3) == '-')) ||
+ ((CUR == '<') && (NXT(1) == '?'))) {
+ htmlParseComment(ctxt);
+ htmlParsePI(ctxt);
+ SKIP_BLANKS;
+ }
+
+ /*
+ * Time to start parsing the tree itself
+ */
+ htmlParseContent(ctxt);
+
+ /*
+ * autoclose
+ */
+ if (CUR == 0)
+ htmlAutoCloseOnEnd(ctxt);
+
+
+ /*
+ * SAX: end of the document processing.
+ */
+ if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
+ ctxt->sax->endDocument(ctxt->userData);
+
+ if (ctxt->myDoc != NULL) {
+ 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");
+ }
+ if (! ctxt->wellFormed) return(-1);
+ return(0);
+}
+
+
+/************************************************************************
+ * *
+ * Parser contexts handling *
+ * *
+ ************************************************************************/
+
+/**
+ * htmlInitParserCtxt:
+ * @ctxt: an HTML parser context
+ *
+ * Initialize a parser context
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+
+static int
+htmlInitParserCtxt(htmlParserCtxtPtr ctxt)
+{
+ htmlSAXHandler *sax;
+
+ if (ctxt == NULL) return(-1);
+ memset(ctxt, 0, sizeof(htmlParserCtxt));
+
+ ctxt->dict = xmlDictCreate();
+ if (ctxt->dict == NULL) {
+ htmlErrMemory(NULL, "htmlInitParserCtxt: out of memory\n");
+ return(-1);
+ }
+ sax = (htmlSAXHandler *) xmlMalloc(sizeof(htmlSAXHandler));
+ if (sax == NULL) {
+ htmlErrMemory(NULL, "htmlInitParserCtxt: out of memory\n");
+ return(-1);
+ }
+ else
+ memset(sax, 0, sizeof(htmlSAXHandler));
+
+ /* Allocate the Input stack */
+ ctxt->inputTab = (htmlParserInputPtr *)
+ xmlMalloc(5 * sizeof(htmlParserInputPtr));
+ if (ctxt->inputTab == NULL) {
+ htmlErrMemory(NULL, "htmlInitParserCtxt: out of memory\n");
+ ctxt->inputNr = 0;
+ ctxt->inputMax = 0;
+ ctxt->input = NULL;
+ return(-1);
+ }
+ ctxt->inputNr = 0;
+ ctxt->inputMax = 5;
+ ctxt->input = NULL;
+ ctxt->version = NULL;
+ ctxt->encoding = NULL;
+ ctxt->standalone = -1;
+ ctxt->instate = XML_PARSER_START;
+
+ /* Allocate the Node stack */
+ ctxt->nodeTab = (htmlNodePtr *) xmlMalloc(10 * sizeof(htmlNodePtr));
+ if (ctxt->nodeTab == NULL) {
+ htmlErrMemory(NULL, "htmlInitParserCtxt: out of memory\n");
+ ctxt->nodeNr = 0;
+ ctxt->nodeMax = 0;
+ ctxt->node = NULL;
+ ctxt->inputNr = 0;
+ ctxt->inputMax = 0;
+ ctxt->input = NULL;
+ return(-1);
+ }
+ ctxt->nodeNr = 0;
+ ctxt->nodeMax = 10;
+ ctxt->node = NULL;
+
+ /* Allocate the Name stack */
+ ctxt->nameTab = (const xmlChar **) xmlMalloc(10 * sizeof(xmlChar *));
+ if (ctxt->nameTab == NULL) {
+ htmlErrMemory(NULL, "htmlInitParserCtxt: out of memory\n");
+ ctxt->nameNr = 0;
+ ctxt->nameMax = 10;
+ ctxt->name = NULL;
+ ctxt->nodeNr = 0;
+ ctxt->nodeMax = 0;
+ ctxt->node = NULL;
+ ctxt->inputNr = 0;
+ ctxt->inputMax = 0;
+ ctxt->input = NULL;
+ return(-1);
+ }
+ ctxt->nameNr = 0;
+ ctxt->nameMax = 10;
+ ctxt->name = NULL;
+
+ if (sax == NULL) ctxt->sax = (xmlSAXHandlerPtr) &htmlDefaultSAXHandler;
+ else {
+ ctxt->sax = sax;
+ memcpy(sax, &htmlDefaultSAXHandler, sizeof(xmlSAXHandlerV1));
+ }
+ ctxt->userData = ctxt;
+ ctxt->myDoc = NULL;
+ ctxt->wellFormed = 1;
+ ctxt->replaceEntities = 0;
+ ctxt->linenumbers = xmlLineNumbersDefaultValue;
+ ctxt->html = 1;
+ ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_0;
+ ctxt->vctxt.userData = ctxt;
+ ctxt->vctxt.error = xmlParserValidityError;
+ ctxt->vctxt.warning = xmlParserValidityWarning;
+ ctxt->record_info = 0;
+ ctxt->validate = 0;
+ ctxt->nbChars = 0;
+ ctxt->checkIndex = 0;
+ ctxt->catalogs = NULL;
+ xmlInitNodeInfoSeq(&ctxt->node_seq);
+ return(0);
+}
+
+/**
+ * htmlFreeParserCtxt:
+ * @ctxt: an HTML parser context
+ *
+ * Free all the memory used by a parser context. However the parsed
+ * document in ctxt->myDoc is not freed.
+ */
+
+void
+htmlFreeParserCtxt(htmlParserCtxtPtr ctxt)
+{
+ xmlFreeParserCtxt(ctxt);
+}
+
+/**
+ * htmlNewParserCtxt:
+ *
+ * Allocate and initialize a new parser context.
+ *
+ * Returns the htmlParserCtxtPtr or NULL in case of allocation error
+ */
+
+htmlParserCtxtPtr
+htmlNewParserCtxt(void)
+{
+ xmlParserCtxtPtr ctxt;
+
+ ctxt = (xmlParserCtxtPtr) xmlMalloc(sizeof(xmlParserCtxt));
+ if (ctxt == NULL) {
+ htmlErrMemory(NULL, "NewParserCtxt: out of memory\n");
+ return(NULL);
+ }
+ memset(ctxt, 0, sizeof(xmlParserCtxt));
+ if (htmlInitParserCtxt(ctxt) < 0) {
+ htmlFreeParserCtxt(ctxt);
+ return(NULL);
+ }
+ return(ctxt);
+}
+
+/**
+ * htmlCreateMemoryParserCtxt:
+ * @buffer: a pointer to a char array
+ * @size: the size of the array
+ *
+ * Create a parser context for an HTML in-memory document.
+ *
+ * Returns the new parser context or NULL
+ */
+htmlParserCtxtPtr
+htmlCreateMemoryParserCtxt(const char *buffer, int size) {
+ xmlParserCtxtPtr ctxt;
+ xmlParserInputPtr input;
+ xmlParserInputBufferPtr buf;
+
+ if (buffer == NULL)
+ return(NULL);
+ if (size <= 0)
+ return(NULL);
+
+ ctxt = htmlNewParserCtxt();
+ if (ctxt == NULL)
+ return(NULL);
+
+ buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
+ if (buf == NULL) return(NULL);
+
+ input = xmlNewInputStream(ctxt);
+ if (input == NULL) {
+ xmlFreeParserCtxt(ctxt);
+ return(NULL);
+ }
+
+ input->filename = NULL;
+ input->buf = buf;
+ input->base = input->buf->buffer->content;
+ input->cur = input->buf->buffer->content;
+ input->end = &input->buf->buffer->content[input->buf->buffer->use];
+
+ inputPush(ctxt, input);
+ return(ctxt);
+}
+
+/**
+ * htmlCreateDocParserCtxt:
+ * @cur: a pointer to an array of xmlChar
+ * @encoding: a free form C string describing the HTML document encoding, or NULL
+ *
+ * Create a parser context for an HTML document.
+ *
+ * TODO: check the need to add encoding handling there
+ *
+ * Returns the new parser context or NULL
+ */
+static htmlParserCtxtPtr
+htmlCreateDocParserCtxt(const xmlChar *cur,
+ const char *encoding ATTRIBUTE_UNUSED) {
+ int len;
+ htmlParserCtxtPtr ctxt;
+
+ if (cur == NULL)
+ return(NULL);
+ len = xmlStrlen(cur);
+ ctxt = htmlCreateMemoryParserCtxt((char *)cur, len);
+
+ if (encoding != NULL) {
+ xmlCharEncoding enc;
+ xmlCharEncodingHandlerPtr handler;
+
+ if (ctxt->input->encoding != NULL)
+ xmlFree((xmlChar *) ctxt->input->encoding);
+ ctxt->input->encoding = xmlStrdup((const xmlChar *) encoding);
+
+ enc = xmlParseCharEncoding(encoding);
+ /*
+ * registered set of known encodings
+ */
+ if (enc != XML_CHAR_ENCODING_ERROR) {
+ xmlSwitchEncoding(ctxt, enc);
+ if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
+ htmlParseErr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
+ "Unsupported encoding %s\n",
+ (const xmlChar *) encoding, NULL);
+ }
+ } else {
+ /*
+ * fallback for unknown encodings
+ */
+ handler = xmlFindCharEncodingHandler((const char *) encoding);
+ if (handler != NULL) {
+ xmlSwitchToEncoding(ctxt, handler);
+ } else {
+ htmlParseErr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
+ "Unsupported encoding %s\n",
+ (const xmlChar *) encoding, NULL);
+ }
+ }
+ }
+ return(ctxt);
+}
+
+#ifdef LIBXML_PUSH_ENABLED
+/************************************************************************
+ * *
+ * Progressive parsing interfaces *
+ * *
+ ************************************************************************/
+
+/**
+ * htmlParseLookupSequence:
+ * @ctxt: an HTML parser context
+ * @first: the first char to lookup
+ * @next: the next char to lookup or zero
+ * @third: the next char to lookup or zero
+ * @comment: flag to force checking inside comments
+ *
+ * Try to find if a sequence (first, next, third) or just (first next) or
+ * (first) is available in the input stream.
+ * This function has a side effect of (possibly) incrementing ctxt->checkIndex
+ * to avoid rescanning sequences of bytes, it DOES change the state of the
+ * parser, do not use liberally.
+ * This is basically similar to xmlParseLookupSequence()
+ *
+ * Returns the index to the current parsing point if the full sequence
+ * is available, -1 otherwise.
+ */
+static int
+htmlParseLookupSequence(htmlParserCtxtPtr ctxt, xmlChar first,
+ xmlChar next, xmlChar third, int iscomment) {
+ int base, len;
+ htmlParserInputPtr in;
+ const xmlChar *buf;
+ int incomment = 0;
+
+ in = ctxt->input;
+ if (in == NULL) return(-1);
+ base = in->cur - in->base;
+ if (base < 0) return(-1);
+ if (ctxt->checkIndex > base)
+ base = ctxt->checkIndex;
+ if (in->buf == NULL) {
+ buf = in->base;
+ len = in->length;
+ } else {
+ buf = in->buf->buffer->content;
+ len = in->buf->buffer->use;
+ }
+ /* take into account the sequence length */
+ if (third) len -= 2;
+ else if (next) len --;
+ for (;base < len;base++) {
+ if (!incomment && (base + 4 < len) && !iscomment) {
+ if ((buf[base] == '<') && (buf[base + 1] == '!') &&
+ (buf[base + 2] == '-') && (buf[base + 3] == '-')) {
+ incomment = 1;
+ /* do not increment past <! - some people use <!--> */
+ 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 <libxml/xmlversion.h>
+#include <libxml/parser.h>
+
+#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 <string.h> /* for memset() only ! */
+
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <libxml/xmlmemory.h>
+#include <libxml/HTMLparser.h>
+#include <libxml/HTMLtree.h>
+#include <libxml/entities.h>
+#include <libxml/valid.h>
+#include <libxml/xmlerror.h>
+#include <libxml/parserInternals.h>
+#include <libxml/globals.h>
+#include <libxml/uri.h>
+
+/************************************************************************
+ * *
+ * 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. <option selected="selected"> will be
+ * output as <option selected>, as per XSLT 1.0 16.2 "HTML Output Method"
+ *
+ */
+static const char* htmlBooleanAttrs[] = {
+ "checked", "compact", "declare", "defer", "disabled", "ismap",
+ "multiple", "nohref", "noresize", "noshade", "nowrap", "readonly",
+ "selected", NULL
+};
+
+
+/**
+ * htmlIsBooleanAttr:
+ * @name: the name of the attribute to check
+ *
+ * Determine if a given attribute is a boolean attribute.
+ *
+ * returns: false if the attribute is not boolean, true otherwise.
+ */
+int
+htmlIsBooleanAttr(const xmlChar *name)
+{
+ int i = 0;
+
+ while (htmlBooleanAttrs[i] != NULL) {
+ if (xmlStrcasecmp((const xmlChar *)htmlBooleanAttrs[i], name) == 0)
+ return 1;
+ i++;
+ }
+ return 0;
+}
+
+#ifdef LIBXML_OUTPUT_ENABLED
+/************************************************************************
+ * *
+ * Output error handlers *
+ * *
+ ************************************************************************/
+/**
+ * htmlSaveErrMemory:
+ * @extra: extra informations
+ *
+ * Handle an out of memory condition
+ */
+static void
+htmlSaveErrMemory(const char *extra)
+{
+ __xmlSimpleError(XML_FROM_OUTPUT, XML_ERR_NO_MEMORY, NULL, NULL, extra);
+}
+
+/**
+ * htmlSaveErr:
+ * @code: the error number
+ * @node: the location of the error.
+ * @extra: extra informations
+ *
+ * Handle an out of memory condition
+ */
+static void
+htmlSaveErr(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 = "HTML has no DOCTYPE\n";
+ break;
+ default:
+ msg = "unexpected error number\n";
+ }
+ __xmlSimpleError(XML_FROM_OUTPUT, code, node, msg, extra);
+}
+
+/************************************************************************
+ * *
+ * Dumping HTML tree content to a simple buffer *
+ * *
+ ************************************************************************/
+
+static int
+htmlNodeDumpFormat(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur,
+ int format);
+
+/**
+ * htmlNodeDumpFormat:
+ * @buf: the HTML buffer output
+ * @doc: the document
+ * @cur: the current node
+ * @format: should formatting spaces been added
+ *
+ * Dump an HTML node, recursive behaviour,children are printed too.
+ *
+ * Returns the number of byte written or -1 in case of error
+ */
+static int
+htmlNodeDumpFormat(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur,
+ int format) {
+ unsigned int use;
+ int ret;
+ xmlOutputBufferPtr outbuf;
+
+ if (cur == NULL) {
+ return (-1);
+ }
+ if (buf == NULL) {
+ return (-1);
+ }
+ outbuf = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
+ if (outbuf == NULL) {
+ htmlSaveErrMemory("allocating HTML output 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;
+ htmlNodeDumpFormatOutput(outbuf, doc, cur, NULL, format);
+ xmlFree(outbuf);
+ ret = buf->use - use;
+ return (ret);
+}
+
+/**
+ * htmlNodeDump:
+ * @buf: the HTML buffer output
+ * @doc: the document
+ * @cur: the current node
+ *
+ * Dump an HTML node, recursive behaviour,children are printed too,
+ * and formatting returns are added.
+ *
+ * Returns the number of byte written or -1 in case of error
+ */
+int
+htmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur) {
+ xmlInitParser();
+
+ return(htmlNodeDumpFormat(buf, doc, cur, 1));
+}
+
+/**
+ * htmlNodeDumpFileFormat:
+ * @out: the FILE pointer
+ * @doc: the document
+ * @cur: the current node
+ * @encoding: the document encoding
+ * @format: should formatting spaces been added
+ *
+ * Dump an HTML node, recursive behaviour,children are printed too.
+ *
+ * TODO: if encoding == NULL try to save in the doc encoding
+ *
+ * returns: the number of byte written or -1 in case of failure.
+ */
+int
+htmlNodeDumpFileFormat(FILE *out, xmlDocPtr doc,
+ xmlNodePtr cur, const char *encoding, int format) {
+ xmlOutputBufferPtr buf;
+ xmlCharEncodingHandlerPtr handler = NULL;
+ int ret;
+
+ xmlInitParser();
+
+ if (encoding != NULL) {
+ xmlCharEncoding enc;
+
+ enc = xmlParseCharEncoding(encoding);
+ if (enc != XML_CHAR_ENCODING_UTF8) {
+ handler = xmlFindCharEncodingHandler(encoding);
+ if (handler == NULL)
+ return(-1);
+ }
+ }
+
+ /*
+ * Fallback to HTML or ASCII when the encoding is unspecified
+ */
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("HTML");
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("ascii");
+
+ /*
+ * save the content to a temp buffer.
+ */
+ buf = xmlOutputBufferCreateFile(out, handler);
+ if (buf == NULL) return(0);
+
+ htmlNodeDumpFormatOutput(buf, doc, cur, encoding, format);
+
+ ret = xmlOutputBufferClose(buf);
+ return(ret);
+}
+
+/**
+ * htmlNodeDumpFile:
+ * @out: the FILE pointer
+ * @doc: the document
+ * @cur: the current node
+ *
+ * Dump an HTML node, recursive behaviour,children are printed too,
+ * and formatting returns are added.
+ */
+void
+htmlNodeDumpFile(FILE *out, xmlDocPtr doc, xmlNodePtr cur) {
+ htmlNodeDumpFileFormat(out, doc, cur, NULL, 1);
+}
+
+/**
+ * htmlDocDumpMemoryFormat:
+ * @cur: the document
+ * @mem: OUT: the memory pointer
+ * @size: OUT: the memory length
+ * @format: should formatting spaces been added
+ *
+ * Dump an HTML document in memory and return the xmlChar * and it's size.
+ * It's up to the caller to free the memory.
+ */
+void
+htmlDocDumpMemoryFormat(xmlDocPtr cur, xmlChar**mem, int *size, int format) {
+ xmlOutputBufferPtr buf;
+ xmlCharEncodingHandlerPtr handler = NULL;
+ const char *encoding;
+
+ xmlInitParser();
+
+ if ((mem == NULL) || (size == NULL))
+ return;
+ if (cur == NULL) {
+ *mem = NULL;
+ *size = 0;
+ return;
+ }
+
+ encoding = (const char *) htmlGetMetaEncoding(cur);
+
+ if (encoding != NULL) {
+ xmlCharEncoding enc;
+
+ enc = xmlParseCharEncoding(encoding);
+ if (enc != cur->charset) {
+ if (cur->charset != XML_CHAR_ENCODING_UTF8) {
+ /*
+ * Not supported yet
+ */
+ *mem = NULL;
+ *size = 0;
+ return;
+ }
+
+ handler = xmlFindCharEncodingHandler(encoding);
+ if (handler == NULL) {
+ *mem = NULL;
+ *size = 0;
+ return;
+ }
+ } else {
+ handler = xmlFindCharEncodingHandler(encoding);
+ }
+ }
+
+ /*
+ * Fallback to HTML or ASCII when the encoding is unspecified
+ */
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("HTML");
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("ascii");
+
+ buf = xmlAllocOutputBuffer(handler);
+ if (buf == NULL) {
+ *mem = NULL;
+ *size = 0;
+ return;
+ }
+
+ htmlDocContentDumpFormatOutput(buf, cur, NULL, format);
+
+ xmlOutputBufferFlush(buf);
+ if (buf->conv != NULL) {
+ *size = buf->conv->use;
+ *mem = xmlStrndup(buf->conv->content, *size);
+ } else {
+ *size = buf->buffer->use;
+ *mem = xmlStrndup(buf->buffer->content, *size);
+ }
+ (void)xmlOutputBufferClose(buf);
+}
+
+/**
+ * htmlDocDumpMemory:
+ * @cur: the document
+ * @mem: OUT: the memory pointer
+ * @size: OUT: the memory length
+ *
+ * Dump an HTML document in memory and return the xmlChar * and it's size.
+ * It's up to the caller to free the memory.
+ */
+void
+htmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
+ htmlDocDumpMemoryFormat(cur, mem, size, 1);
+}
+
+
+/************************************************************************
+ * *
+ * Dumping HTML tree content to an I/O output buffer *
+ * *
+ ************************************************************************/
+
+void xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur);
+
+/**
+ * htmlDtdDumpOutput:
+ * @buf: the HTML buffer output
+ * @doc: the document
+ * @encoding: the encoding string
+ *
+ * TODO: check whether encoding is needed
+ *
+ * Dump the HTML document DTD, if any.
+ */
+static void
+htmlDtdDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
+ const char *encoding ATTRIBUTE_UNUSED) {
+ xmlDtdPtr cur = doc->intSubset;
+
+ if (cur == NULL) {
+ htmlSaveErr(XML_SAVE_NO_DOCTYPE, (xmlNodePtr) doc, NULL);
+ return;
+ }
+ xmlOutputBufferWriteString(buf, "<!DOCTYPE ");
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ if (cur->ExternalID != NULL) {
+ xmlOutputBufferWriteString(buf, " PUBLIC ");
+ xmlBufferWriteQuotedString(buf->buffer, cur->ExternalID);
+ if (cur->SystemID != NULL) {
+ xmlOutputBufferWriteString(buf, " ");
+ xmlBufferWriteQuotedString(buf->buffer, cur->SystemID);
+ }
+ } else if (cur->SystemID != NULL) {
+ xmlOutputBufferWriteString(buf, " SYSTEM ");
+ xmlBufferWriteQuotedString(buf->buffer, cur->SystemID);
+ }
+ xmlOutputBufferWriteString(buf, ">\n");
+}
+
+/**
+ * htmlAttrDumpOutput:
+ * @buf: the HTML buffer output
+ * @doc: the document
+ * @cur: the attribute pointer
+ * @encoding: the encoding string
+ *
+ * Dump an HTML attribute
+ */
+static void
+htmlAttrDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur,
+ const char *encoding ATTRIBUTE_UNUSED) {
+ xmlChar *value;
+
+ /*
+ * TODO: The html output method should not escape a & character
+ * occurring in an attribute value immediately followed by
+ * a { character (see Section B.7.1 of the HTML 4.0 Recommendation).
+ */
+
+ if (cur == NULL) {
+ return;
+ }
+ xmlOutputBufferWriteString(buf, " ");
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
+ xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
+ xmlOutputBufferWriteString(buf, ":");
+ }
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ if ((cur->children != NULL) && (!htmlIsBooleanAttr(cur->name))) {
+ value = xmlNodeListGetString(doc, cur->children, 0);
+ if (value) {
+ xmlOutputBufferWriteString(buf, "=");
+ if ((cur->ns == NULL) && (cur->parent != NULL) &&
+ (cur->parent->ns == NULL) &&
+ ((!xmlStrcasecmp(cur->name, BAD_CAST "href")) ||
+ (!xmlStrcasecmp(cur->name, BAD_CAST "action")) ||
+ (!xmlStrcasecmp(cur->name, BAD_CAST "src")) ||
+ ((!xmlStrcasecmp(cur->name, BAD_CAST "name")) &&
+ (!xmlStrcasecmp(cur->parent->name, BAD_CAST "a"))))) {
+ xmlChar *escaped;
+ xmlChar *tmp = value;
+
+ while (IS_BLANK_CH(*tmp)) tmp++;
+
+ escaped = xmlURIEscapeStr(tmp, BAD_CAST"@/:=?;#%&,+");
+ if (escaped != NULL) {
+ xmlBufferWriteQuotedString(buf->buffer, escaped);
+ xmlFree(escaped);
+ } else {
+ xmlBufferWriteQuotedString(buf->buffer, value);
+ }
+ } else {
+ xmlBufferWriteQuotedString(buf->buffer, value);
+ }
+ xmlFree(value);
+ } else {
+ xmlOutputBufferWriteString(buf, "=\"\"");
+ }
+ }
+}
+
+/**
+ * htmlAttrListDumpOutput:
+ * @buf: the HTML buffer output
+ * @doc: the document
+ * @cur: the first attribute pointer
+ * @encoding: the encoding string
+ *
+ * Dump a list of HTML attributes
+ */
+static void
+htmlAttrListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur, const char *encoding) {
+ if (cur == NULL) {
+ return;
+ }
+ while (cur != NULL) {
+ htmlAttrDumpOutput(buf, doc, cur, encoding);
+ cur = cur->next;
+ }
+}
+
+
+
+/**
+ * htmlNodeListDumpOutput:
+ * @buf: the HTML buffer output
+ * @doc: the document
+ * @cur: the first node
+ * @encoding: the encoding string
+ * @format: should formatting spaces been added
+ *
+ * Dump an HTML node list, recursive behaviour,children are printed too.
+ */
+static void
+htmlNodeListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
+ xmlNodePtr cur, const char *encoding, int format) {
+ if (cur == NULL) {
+ return;
+ }
+ while (cur != NULL) {
+ htmlNodeDumpFormatOutput(buf, doc, cur, encoding, format);
+ cur = cur->next;
+ }
+}
+
+/**
+ * htmlNodeDumpFormatOutput:
+ * @buf: the HTML buffer output
+ * @doc: the document
+ * @cur: the current node
+ * @encoding: the encoding string
+ * @format: should formatting spaces been added
+ *
+ * Dump an HTML node, recursive behaviour,children are printed too.
+ */
+void
+htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
+ xmlNodePtr cur, const char *encoding, int format) {
+ const htmlElemDesc * info;
+
+ xmlInitParser();
+
+ if ((cur == NULL) || (buf == NULL)) {
+ return;
+ }
+ /*
+ * Special cases.
+ */
+ if (cur->type == XML_DTD_NODE)
+ return;
+ if ((cur->type == XML_HTML_DOCUMENT_NODE) ||
+ (cur->type == XML_DOCUMENT_NODE)){
+ htmlDocContentDumpOutput(buf, (xmlDocPtr) cur, encoding);
+ return;
+ }
+ if (cur->type == HTML_TEXT_NODE) {
+ if (cur->content != NULL) {
+ if (((cur->name == (const xmlChar *)xmlStringText) ||
+ (cur->name != (const xmlChar *)xmlStringTextNoenc)) &&
+ ((cur->parent == NULL) ||
+ ((xmlStrcasecmp(cur->parent->name, BAD_CAST "script")) &&
+ (xmlStrcasecmp(cur->parent->name, BAD_CAST "style"))))) {
+ xmlChar *buffer;
+
+ buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
+ if (buffer != NULL) {
+ xmlOutputBufferWriteString(buf, (const char *)buffer);
+ xmlFree(buffer);
+ }
+ } else {
+ xmlOutputBufferWriteString(buf, (const char *)cur->content);
+ }
+ }
+ return;
+ }
+ if (cur->type == HTML_COMMENT_NODE) {
+ if (cur->content != NULL) {
+ xmlOutputBufferWriteString(buf, "<!--");
+ xmlOutputBufferWriteString(buf, (const char *)cur->content);
+ xmlOutputBufferWriteString(buf, "-->");
+ }
+ return;
+ }
+ if (cur->type == HTML_PI_NODE) {
+ if (cur->name == NULL)
+ return;
+ xmlOutputBufferWriteString(buf, "<?");
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ if (cur->content != NULL) {
+ xmlOutputBufferWriteString(buf, " ");
+ xmlOutputBufferWriteString(buf, (const char *)cur->content);
+ }
+ xmlOutputBufferWriteString(buf, ">");
+ return;
+ }
+ if (cur->type == HTML_ENTITY_REF_NODE) {
+ xmlOutputBufferWriteString(buf, "&");
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ xmlOutputBufferWriteString(buf, ";");
+ return;
+ }
+ if (cur->type == HTML_PRESERVE_NODE) {
+ if (cur->content != NULL) {
+ xmlOutputBufferWriteString(buf, (const char *)cur->content);
+ }
+ return;
+ }
+
+ /*
+ * Get specific HTML info for that node.
+ */
+ if (cur->ns == NULL)
+ info = htmlTagLookup(cur->name);
+ else
+ info = NULL;
+
+ xmlOutputBufferWriteString(buf, "<");
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
+ xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
+ xmlOutputBufferWriteString(buf, ":");
+ }
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ if (cur->nsDef)
+ xmlNsListDumpOutput(buf, cur->nsDef);
+ if (cur->properties != NULL)
+ htmlAttrListDumpOutput(buf, doc, cur->properties, encoding);
+
+ if ((info != NULL) && (info->empty)) {
+ xmlOutputBufferWriteString(buf, ">");
+ if ((format) && (!info->isinline) && (cur->next != NULL)) {
+ if ((cur->next->type != HTML_TEXT_NODE) &&
+ (cur->next->type != HTML_ENTITY_REF_NODE) &&
+ (cur->parent != NULL) &&
+ (cur->parent->name != NULL) &&
+ (cur->parent->name[0] != 'p')) /* p, pre, param */
+ xmlOutputBufferWriteString(buf, "\n");
+ }
+ return;
+ }
+ if (((cur->type == XML_ELEMENT_NODE) || (cur->content == NULL)) &&
+ (cur->children == NULL)) {
+ if ((info != NULL) && (info->saveEndTag != 0) &&
+ (xmlStrcmp(BAD_CAST info->name, BAD_CAST "html")) &&
+ (xmlStrcmp(BAD_CAST info->name, BAD_CAST "body"))) {
+ xmlOutputBufferWriteString(buf, ">");
+ } else {
+ xmlOutputBufferWriteString(buf, "></");
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
+ xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
+ xmlOutputBufferWriteString(buf, ":");
+ }
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ xmlOutputBufferWriteString(buf, ">");
+ }
+ if ((format) && (cur->next != NULL) &&
+ (info != NULL) && (!info->isinline)) {
+ if ((cur->next->type != HTML_TEXT_NODE) &&
+ (cur->next->type != HTML_ENTITY_REF_NODE) &&
+ (cur->parent != NULL) &&
+ (cur->parent->name != NULL) &&
+ (cur->parent->name[0] != 'p')) /* p, pre, param */
+ xmlOutputBufferWriteString(buf, "\n");
+ }
+ return;
+ }
+ xmlOutputBufferWriteString(buf, ">");
+ if ((cur->type != XML_ELEMENT_NODE) &&
+ (cur->content != NULL)) {
+ /*
+ * Uses the OutputBuffer property to automatically convert
+ * invalids to charrefs
+ */
+
+ xmlOutputBufferWriteString(buf, (const char *) cur->content);
+ }
+ if (cur->children != NULL) {
+ if ((format) && (info != NULL) && (!info->isinline) &&
+ (cur->children->type != HTML_TEXT_NODE) &&
+ (cur->children->type != HTML_ENTITY_REF_NODE) &&
+ (cur->children != cur->last) &&
+ (cur->name != NULL) &&
+ (cur->name[0] != 'p')) /* p, pre, param */
+ xmlOutputBufferWriteString(buf, "\n");
+ htmlNodeListDumpOutput(buf, doc, cur->children, encoding, format);
+ if ((format) && (info != NULL) && (!info->isinline) &&
+ (cur->last->type != HTML_TEXT_NODE) &&
+ (cur->last->type != HTML_ENTITY_REF_NODE) &&
+ (cur->children != cur->last) &&
+ (cur->name != NULL) &&
+ (cur->name[0] != 'p')) /* p, pre, param */
+ xmlOutputBufferWriteString(buf, "\n");
+ }
+ xmlOutputBufferWriteString(buf, "</");
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
+ xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
+ xmlOutputBufferWriteString(buf, ":");
+ }
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ xmlOutputBufferWriteString(buf, ">");
+ if ((format) && (info != NULL) && (!info->isinline) &&
+ (cur->next != NULL)) {
+ if ((cur->next->type != HTML_TEXT_NODE) &&
+ (cur->next->type != HTML_ENTITY_REF_NODE) &&
+ (cur->parent != NULL) &&
+ (cur->parent->name != NULL) &&
+ (cur->parent->name[0] != 'p')) /* p, pre, param */
+ xmlOutputBufferWriteString(buf, "\n");
+ }
+}
+
+/**
+ * htmlNodeDumpOutput:
+ * @buf: the HTML buffer output
+ * @doc: the document
+ * @cur: the current node
+ * @encoding: the encoding string
+ *
+ * Dump an HTML node, recursive behaviour,children are printed too,
+ * and formatting returns/spaces are added.
+ */
+void
+htmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
+ xmlNodePtr cur, const char *encoding) {
+ htmlNodeDumpFormatOutput(buf, doc, cur, encoding, 1);
+}
+
+/**
+ * htmlDocContentDumpFormatOutput:
+ * @buf: the HTML buffer output
+ * @cur: the document
+ * @encoding: the encoding string
+ * @format: should formatting spaces been added
+ *
+ * Dump an HTML document.
+ */
+void
+htmlDocContentDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr cur,
+ const char *encoding, int format) {
+ int type;
+
+ xmlInitParser();
+
+ if ((buf == NULL) || (cur == NULL))
+ return;
+
+ /*
+ * force to output the stuff as HTML, especially for entities
+ */
+ type = cur->type;
+ cur->type = XML_HTML_DOCUMENT_NODE;
+ if (cur->intSubset != NULL) {
+ htmlDtdDumpOutput(buf, cur, NULL);
+ }
+ if (cur->children != NULL) {
+ htmlNodeListDumpOutput(buf, cur, cur->children, encoding, format);
+ }
+ xmlOutputBufferWriteString(buf, "\n");
+ cur->type = (xmlElementType) type;
+}
+
+/**
+ * htmlDocContentDumpOutput:
+ * @buf: the HTML buffer output
+ * @cur: the document
+ * @encoding: the encoding string
+ *
+ * Dump an HTML document. Formating return/spaces are added.
+ */
+void
+htmlDocContentDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr cur,
+ const char *encoding) {
+ htmlDocContentDumpFormatOutput(buf, cur, encoding, 1);
+}
+
+/************************************************************************
+ * *
+ * Saving functions front-ends *
+ * *
+ ************************************************************************/
+
+/**
+ * htmlDocDump:
+ * @f: the FILE*
+ * @cur: the document
+ *
+ * Dump an HTML document to an open FILE.
+ *
+ * returns: the number of byte written or -1 in case of failure.
+ */
+int
+htmlDocDump(FILE *f, xmlDocPtr cur) {
+ xmlOutputBufferPtr buf;
+ xmlCharEncodingHandlerPtr handler = NULL;
+ const char *encoding;
+ int ret;
+
+ xmlInitParser();
+
+ if ((cur == NULL) || (f == NULL)) {
+ return(-1);
+ }
+
+ encoding = (const char *) htmlGetMetaEncoding(cur);
+
+ if (encoding != NULL) {
+ xmlCharEncoding enc;
+
+ enc = xmlParseCharEncoding(encoding);
+ if (enc != cur->charset) {
+ if (cur->charset != XML_CHAR_ENCODING_UTF8) {
+ /*
+ * Not supported yet
+ */
+ return(-1);
+ }
+
+ handler = xmlFindCharEncodingHandler(encoding);
+ if (handler == NULL)
+ return(-1);
+ } else {
+ handler = xmlFindCharEncodingHandler(encoding);
+ }
+ }
+
+ /*
+ * Fallback to HTML or ASCII when the encoding is unspecified
+ */
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("HTML");
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("ascii");
+
+ buf = xmlOutputBufferCreateFile(f, handler);
+ if (buf == NULL) return(-1);
+ htmlDocContentDumpOutput(buf, cur, NULL);
+
+ ret = xmlOutputBufferClose(buf);
+ return(ret);
+}
+
+/**
+ * htmlSaveFile:
+ * @filename: the filename (or URL)
+ * @cur: the document
+ *
+ * Dump an HTML document to a file. If @filename is "-" the stdout file is
+ * used.
+ * returns: the number of byte written or -1 in case of failure.
+ */
+int
+htmlSaveFile(const char *filename, xmlDocPtr cur) {
+ xmlOutputBufferPtr buf;
+ xmlCharEncodingHandlerPtr handler = NULL;
+ const char *encoding;
+ int ret;
+
+ if ((cur == NULL) || (filename == NULL))
+ return(-1);
+
+ xmlInitParser();
+
+ encoding = (const char *) htmlGetMetaEncoding(cur);
+
+ if (encoding != NULL) {
+ xmlCharEncoding enc;
+
+ enc = xmlParseCharEncoding(encoding);
+ if (enc != cur->charset) {
+ if (cur->charset != XML_CHAR_ENCODING_UTF8) {
+ /*
+ * Not supported yet
+ */
+ return(-1);
+ }
+
+ handler = xmlFindCharEncodingHandler(encoding);
+ if (handler == NULL)
+ return(-1);
+ }
+ }
+
+ /*
+ * Fallback to HTML or ASCII when the encoding is unspecified
+ */
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("HTML");
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("ascii");
+
+ /*
+ * save the content to a temp buffer.
+ */
+ buf = xmlOutputBufferCreateFilename(filename, handler, cur->compression);
+ if (buf == NULL) return(0);
+
+ htmlDocContentDumpOutput(buf, cur, NULL);
+
+ ret = xmlOutputBufferClose(buf);
+ return(ret);
+}
+
+/**
+ * htmlSaveFileFormat:
+ * @filename: the filename
+ * @cur: the document
+ * @format: should formatting spaces been added
+ * @encoding: the document encoding
+ *
+ * Dump an HTML document to a file using a given encoding.
+ *
+ * returns: the number of byte written or -1 in case of failure.
+ */
+int
+htmlSaveFileFormat(const char *filename, xmlDocPtr cur,
+ const char *encoding, int format) {
+ xmlOutputBufferPtr buf;
+ xmlCharEncodingHandlerPtr handler = NULL;
+ int ret;
+
+ if ((cur == NULL) || (filename == NULL))
+ return(-1);
+
+ xmlInitParser();
+
+ if (encoding != NULL) {
+ xmlCharEncoding enc;
+
+ enc = xmlParseCharEncoding(encoding);
+ if (enc != cur->charset) {
+ if (cur->charset != XML_CHAR_ENCODING_UTF8) {
+ /*
+ * Not supported yet
+ */
+ return(-1);
+ }
+
+ handler = xmlFindCharEncodingHandler(encoding);
+ if (handler == NULL)
+ return(-1);
+ htmlSetMetaEncoding(cur, (const xmlChar *) encoding);
+ }
+ } else {
+ htmlSetMetaEncoding(cur, (const xmlChar *) "UTF-8");
+ }
+
+ /*
+ * Fallback to HTML or ASCII when the encoding is unspecified
+ */
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("HTML");
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("ascii");
+
+ /*
+ * save the content to a temp buffer.
+ */
+ buf = xmlOutputBufferCreateFilename(filename, handler, 0);
+ if (buf == NULL) return(0);
+
+ htmlDocContentDumpFormatOutput(buf, cur, encoding, format);
+
+ ret = xmlOutputBufferClose(buf);
+ return(ret);
+}
+
+/**
+ * htmlSaveFileEnc:
+ * @filename: the filename
+ * @cur: the document
+ * @encoding: the document encoding
+ *
+ * Dump an HTML document to a file using a given encoding
+ * and formatting returns/spaces are added.
+ *
+ * returns: the number of byte written or -1 in case of failure.
+ */
+int
+htmlSaveFileEnc(const char *filename, xmlDocPtr cur, const char *encoding) {
+ return(htmlSaveFileFormat(filename, cur, encoding, 1));
+}
+
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+#define bottom_HTMLtree
+#include "elfgcchack.h"
+#endif /* LIBXML_HTML_ENABLED */
diff --git a/gettext-tools/gnulib-lib/libxml/HTMLtree.in.h b/gettext-tools/gnulib-lib/libxml/HTMLtree.in.h
new file mode 100644
index 0000000..6ea8207
--- /dev/null
+++ b/gettext-tools/gnulib-lib/libxml/HTMLtree.in.h
@@ -0,0 +1,147 @@
+/*
+ * Summary: specific APIs to process HTML tree, especially serialization
+ * Description: this module implements a few function needed to process
+ * tree in an HTML specific way.
+ *
+ * Copy: See Copyright for the status of this software.
+ *
+ * Author: Daniel Veillard
+ */
+
+#ifndef __HTML_TREE_H__
+#define __HTML_TREE_H__
+
+#include <stdio.h>
+#include <libxml/xmlversion.h>
+#include <libxml/tree.h>
+#include <libxml/HTMLparser.h>
+
+#ifdef LIBXML_HTML_ENABLED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * HTML_TEXT_NODE:
+ *
+ * Macro. A text node in a HTML document is really implemented
+ * the same way as a text node in an XML document.
+ */
+#define HTML_TEXT_NODE XML_TEXT_NODE
+/**
+ * HTML_ENTITY_REF_NODE:
+ *
+ * Macro. An entity reference in a HTML document is really implemented
+ * the same way as an entity reference in an XML document.
+ */
+#define HTML_ENTITY_REF_NODE XML_ENTITY_REF_NODE
+/**
+ * HTML_COMMENT_NODE:
+ *
+ * Macro. A comment in a HTML document is really implemented
+ * the same way as a comment in an XML document.
+ */
+#define HTML_COMMENT_NODE XML_COMMENT_NODE
+/**
+ * HTML_PRESERVE_NODE:
+ *
+ * Macro. A preserved node in a HTML document is really implemented
+ * the same way as a CDATA section in an XML document.
+ */
+#define HTML_PRESERVE_NODE XML_CDATA_SECTION_NODE
+/**
+ * HTML_PI_NODE:
+ *
+ * Macro. A processing instruction in a HTML document is really implemented
+ * the same way as a processing instruction in an XML document.
+ */
+#define HTML_PI_NODE XML_PI_NODE
+
+XMLPUBFUN htmlDocPtr XMLCALL
+ htmlNewDoc (const xmlChar *URI,
+ const xmlChar *ExternalID);
+XMLPUBFUN htmlDocPtr XMLCALL
+ htmlNewDocNoDtD (const xmlChar *URI,
+ const xmlChar *ExternalID);
+XMLPUBFUN const xmlChar * XMLCALL
+ htmlGetMetaEncoding (htmlDocPtr doc);
+XMLPUBFUN int XMLCALL
+ htmlSetMetaEncoding (htmlDocPtr doc,
+ const xmlChar *encoding);
+#ifdef LIBXML_OUTPUT_ENABLED
+XMLPUBFUN void XMLCALL
+ htmlDocDumpMemory (xmlDocPtr cur,
+ xmlChar **mem,
+ int *size);
+XMLPUBFUN void XMLCALL
+ htmlDocDumpMemoryFormat (xmlDocPtr cur,
+ xmlChar **mem,
+ int *size,
+ int format);
+XMLPUBFUN int XMLCALL
+ htmlDocDump (FILE *f,
+ xmlDocPtr cur);
+XMLPUBFUN int XMLCALL
+ htmlSaveFile (const char *filename,
+ xmlDocPtr cur);
+XMLPUBFUN int XMLCALL
+ htmlNodeDump (xmlBufferPtr buf,
+ xmlDocPtr doc,
+ xmlNodePtr cur);
+XMLPUBFUN void XMLCALL
+ htmlNodeDumpFile (FILE *out,
+ xmlDocPtr doc,
+ xmlNodePtr cur);
+XMLPUBFUN int XMLCALL
+ htmlNodeDumpFileFormat (FILE *out,
+ xmlDocPtr doc,
+ xmlNodePtr cur,
+ const char *encoding,
+ int format);
+XMLPUBFUN int XMLCALL
+ htmlSaveFileEnc (const char *filename,
+ xmlDocPtr cur,
+ const char *encoding);
+XMLPUBFUN int XMLCALL
+ htmlSaveFileFormat (const char *filename,
+ xmlDocPtr cur,
+ const char *encoding,
+ int format);
+
+XMLPUBFUN void XMLCALL
+ htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf,
+ xmlDocPtr doc,
+ xmlNodePtr cur,
+ const char *encoding,
+ int format);
+XMLPUBFUN void XMLCALL
+ htmlDocContentDumpOutput(xmlOutputBufferPtr buf,
+ xmlDocPtr cur,
+ const char *encoding);
+XMLPUBFUN void XMLCALL
+ htmlDocContentDumpFormatOutput(xmlOutputBufferPtr buf,
+ xmlDocPtr cur,
+ const char *encoding,
+ int format);
+XMLPUBFUN void XMLCALL
+ htmlNodeDumpOutput (xmlOutputBufferPtr buf,
+ xmlDocPtr doc,
+ xmlNodePtr cur,
+ const char *encoding);
+
+#endif /* LIBXML_OUTPUT_ENABLED */
+
+XMLPUBFUN int XMLCALL
+ htmlIsBooleanAttr (const xmlChar *name);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LIBXML_HTML_ENABLED */
+
+#endif /* __HTML_TREE_H__ */
+
diff --git a/gettext-tools/gnulib-lib/libxml/SAX.c b/gettext-tools/gnulib-lib/libxml/SAX.c
new file mode 100644
index 0000000..8e5d460
--- /dev/null
+++ b/gettext-tools/gnulib-lib/libxml/SAX.c
@@ -0,0 +1,180 @@
+/*
+ * SAX.c : Old SAX v1 handlers to build a tree.
+ * Deprecated except for compatibility
+ *
+ * See Copyright for the status of this software.
+ *
+ * Daniel Veillard <daniel@veillard.com>
+ */
+
+
+#define IN_LIBXML
+#include "libxml.h"
+#include <stdlib.h>
+#include <string.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/valid.h>
+#include <libxml/entities.h>
+#include <libxml/xmlerror.h>
+#include <libxml/debugXML.h>
+#include <libxml/xmlIO.h>
+#include <libxml/SAX.h>
+#include <libxml/uri.h>
+#include <libxml/valid.h>
+#include <libxml/HTMLtree.h>
+#include <libxml/globals.h>
+#include <libxml/SAX2.h>
+
+#ifdef LIBXML_LEGACY_ENABLED
+#ifdef LIBXML_SAX1_ENABLED
+/**
+ * initxmlDefaultSAXHandler:
+ * @hdlr: the SAX handler
+ * @warning: flag if non-zero sets the handler warning procedure
+ *
+ * Initialize the default XML SAX version 1 handler
+ * DEPRECATED: use xmlSAX2InitDefaultSAXHandler() for the new SAX2 blocks
+ */
+void
+initxmlDefaultSAXHandler(xmlSAXHandlerV1 *hdlr, int warning)
+{
+
+ if(hdlr->initialized == 1)
+ return;
+
+ 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->startElement = xmlSAX2StartElement;
+ hdlr->endElement = xmlSAX2EndElement;
+ hdlr->reference = xmlSAX2Reference;
+ hdlr->characters = xmlSAX2Characters;
+ hdlr->cdataBlock = xmlSAX2CDataBlock;
+ hdlr->ignorableWhitespace = xmlSAX2Characters;
+ hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
+ if (warning == 0)
+ hdlr->warning = NULL;
+ else
+ hdlr->warning = xmlParserWarning;
+ hdlr->error = xmlParserError;
+ hdlr->fatalError = xmlParserError;
+
+ hdlr->initialized = 1;
+}
+
+#ifdef LIBXML_HTML_ENABLED
+
+/**
+ * inithtmlDefaultSAXHandler:
+ * @hdlr: the SAX handler
+ *
+ * Initialize the default HTML SAX version 1 handler
+ * DEPRECATED: use xmlSAX2InitHtmlDefaultSAXHandler() for the new SAX2 blocks
+ */
+void
+inithtmlDefaultSAXHandler(xmlSAXHandlerV1 *hdlr)
+{
+ if(hdlr->initialized == 1)
+ 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;
+}
+
+#endif /* LIBXML_HTML_ENABLED */
+
+#ifdef LIBXML_DOCB_ENABLED
+/**
+ * initdocbDefaultSAXHandler:
+ * @hdlr: the SAX handler
+ *
+ * Initialize the default DocBook SAX version 1 handler
+ * DEPRECATED: use xmlSAX2InitDocbDefaultSAXHandler() for the new SAX2 blocks
+ */
+void
+initdocbDefaultSAXHandler(xmlSAXHandlerV1 *hdlr)
+{
+ if(hdlr->initialized == 1)
+ 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;
+}
+
+#endif /* LIBXML_DOCB_ENABLED */
+
+#endif /* LIBXML_SAX1_ENABLED */
+
+#define bottom_SAX
+#include "elfgcchack.h"
+#endif /* LIBXML_LEGACY_ENABLED */
diff --git a/gettext-tools/gnulib-lib/libxml/SAX.in.h b/gettext-tools/gnulib-lib/libxml/SAX.in.h
new file mode 100644
index 0000000..0ca161b
--- /dev/null
+++ b/gettext-tools/gnulib-lib/libxml/SAX.in.h
@@ -0,0 +1,173 @@
+/*
+ * Summary: Old SAX version 1 handler, deprecated
+ * Description: DEPRECATED set of SAX version 1 interfaces used to
+ * build the DOM tree.
+ *
+ * Copy: See Copyright for the status of this software.
+ *
+ * Author: Daniel Veillard
+ */
+
+
+#ifndef __XML_SAX_H__
+#define __XML_SAX_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <libxml/xmlversion.h>
+#include <libxml/parser.h>
+#include <libxml/xlink.h>
+
+#ifdef LIBXML_LEGACY_ENABLED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+XMLPUBFUN const xmlChar * XMLCALL
+ getPublicId (void *ctx);
+XMLPUBFUN const xmlChar * XMLCALL
+ getSystemId (void *ctx);
+XMLPUBFUN void XMLCALL
+ setDocumentLocator (void *ctx,
+ xmlSAXLocatorPtr loc);
+
+XMLPUBFUN int XMLCALL
+ getLineNumber (void *ctx);
+XMLPUBFUN int XMLCALL
+ getColumnNumber (void *ctx);
+
+XMLPUBFUN int XMLCALL
+ isStandalone (void *ctx);
+XMLPUBFUN int XMLCALL
+ hasInternalSubset (void *ctx);
+XMLPUBFUN int XMLCALL
+ hasExternalSubset (void *ctx);
+
+XMLPUBFUN void XMLCALL
+ internalSubset (void *ctx,
+ const xmlChar *name,
+ const xmlChar *ExternalID,
+ const xmlChar *SystemID);
+XMLPUBFUN void XMLCALL
+ externalSubset (void *ctx,
+ const xmlChar *name,
+ const xmlChar *ExternalID,
+ const xmlChar *SystemID);
+XMLPUBFUN xmlEntityPtr XMLCALL
+ getEntity (void *ctx,
+ const xmlChar *name);
+XMLPUBFUN xmlEntityPtr XMLCALL
+ getParameterEntity (void *ctx,
+ const xmlChar *name);
+XMLPUBFUN xmlParserInputPtr XMLCALL
+ resolveEntity (void *ctx,
+ const xmlChar *publicId,
+ const xmlChar *systemId);
+
+XMLPUBFUN void XMLCALL
+ entityDecl (void *ctx,
+ const xmlChar *name,
+ int type,
+ const xmlChar *publicId,
+ const xmlChar *systemId,
+ xmlChar *content);
+XMLPUBFUN void XMLCALL
+ attributeDecl (void *ctx,
+ const xmlChar *elem,
+ const xmlChar *fullname,
+ int type,
+ int def,
+ const xmlChar *defaultValue,
+ xmlEnumerationPtr tree);
+XMLPUBFUN void XMLCALL
+ elementDecl (void *ctx,
+ const xmlChar *name,
+ int type,
+ xmlElementContentPtr content);
+XMLPUBFUN void XMLCALL
+ notationDecl (void *ctx,
+ const xmlChar *name,
+ const xmlChar *publicId,
+ const xmlChar *systemId);
+XMLPUBFUN void XMLCALL
+ unparsedEntityDecl (void *ctx,
+ const xmlChar *name,
+ const xmlChar *publicId,
+ const xmlChar *systemId,
+ const xmlChar *notationName);
+
+XMLPUBFUN void XMLCALL
+ startDocument (void *ctx);
+XMLPUBFUN void XMLCALL
+ endDocument (void *ctx);
+XMLPUBFUN void XMLCALL
+ attribute (void *ctx,
+ const xmlChar *fullname,
+ const xmlChar *value);
+XMLPUBFUN void XMLCALL
+ startElement (void *ctx,
+ const xmlChar *fullname,
+ const xmlChar **atts);
+XMLPUBFUN void XMLCALL
+ endElement (void *ctx,
+ const xmlChar *name);
+XMLPUBFUN void XMLCALL
+ reference (void *ctx,
+ const xmlChar *name);
+XMLPUBFUN void XMLCALL
+ characters (void *ctx,
+ const xmlChar *ch,
+ int len);
+XMLPUBFUN void XMLCALL
+ ignorableWhitespace (void *ctx,
+ const xmlChar *ch,
+ int len);
+XMLPUBFUN void XMLCALL
+ processingInstruction (void *ctx,
+ const xmlChar *target,
+ const xmlChar *data);
+XMLPUBFUN void XMLCALL
+ globalNamespace (void *ctx,
+ const xmlChar *href,
+ const xmlChar *prefix);
+XMLPUBFUN void XMLCALL
+ setNamespace (void *ctx,
+ const xmlChar *name);
+XMLPUBFUN xmlNsPtr XMLCALL
+ getNamespace (void *ctx);
+XMLPUBFUN int XMLCALL
+ checkNamespace (void *ctx,
+ xmlChar *nameSpace);
+XMLPUBFUN void XMLCALL
+ namespaceDecl (void *ctx,
+ const xmlChar *href,
+ const xmlChar *prefix);
+XMLPUBFUN void XMLCALL
+ comment (void *ctx,
+ const xmlChar *value);
+XMLPUBFUN void XMLCALL
+ cdataBlock (void *ctx,
+ const xmlChar *value,
+ int len);
+
+#ifdef LIBXML_SAX1_ENABLED
+XMLPUBFUN void XMLCALL
+ initxmlDefaultSAXHandler (xmlSAXHandlerV1 *hdlr,
+ int warning);
+#ifdef LIBXML_HTML_ENABLED
+XMLPUBFUN void XMLCALL
+ inithtmlDefaultSAXHandler (xmlSAXHandlerV1 *hdlr);
+#endif
+#ifdef LIBXML_DOCB_ENABLED
+XMLPUBFUN void XMLCALL
+ initdocbDefaultSAXHandler (xmlSAXHandlerV1 *hdlr);
+#endif
+#endif /* LIBXML_SAX1_ENABLED */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LIBXML_LEGACY_ENABLED */
+
+#endif /* __XML_SAX_H__ */
diff --git a/gettext-tools/gnulib-lib/libxml/SAX2.c b/gettext-tools/gnulib-lib/libxml/SAX2.c
new file mode 100644
index 0000000..7d4ab64
--- /dev/null
+++ b/gettext-tools/gnulib-lib/libxml/SAX2.c
@@ -0,0 +1,2891 @@
+/*
+ * SAX2.c : Default SAX2 handler to build a tree.
+ *
+ * See Copyright for the status of this software.
+ *
+ * Daniel Veillard <daniel@veillard.com>
+ */
+
+
+#define IN_LIBXML
+#include "libxml.h"
+#include <stdlib.h>
+#include <string.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/valid.h>
+#include <libxml/entities.h>
+#include <libxml/xmlerror.h>
+#include <libxml/debugXML.h>
+#include <libxml/xmlIO.h>
+#include <libxml/SAX.h>
+#include <libxml/uri.h>
+#include <libxml/valid.h>
+#include <libxml/HTMLtree.h>
+#include <libxml/globals.h>
+
+/* #define DEBUG_SAX2 */
+/* #define DEBUG_SAX2_TREE */
+
+/**
+ * TODO:
+ *
+ * macro to flag unimplemented blocks
+ * XML_CATALOG_PREFER user env to select between system/public prefered
+ * option. C.f. Richard Tobin <richard@cogsci.ed.ac.uk>
+ *> 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__);
+
+/*
+ * xmlSAX2ErrMemory:
+ * @ctxt: an XML validation parser context
+ * @msg: a string to accompany the error message
+ */
+static void
+xmlSAX2ErrMemory(xmlParserCtxtPtr ctxt, const char *msg) {
+ if (ctxt != NULL) {
+ if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+ ctxt->sax->error(ctxt->userData, "%s: out of memory\n", msg);
+ ctxt->errNo = XML_ERR_NO_MEMORY;
+ ctxt->instate = XML_PARSER_EOF;
+ ctxt->disableSAX = 1;
+ }
+}
+
+/**
+ * xmlValidError:
+ * @ctxt: an XML validation parser context
+ * @error: the error number
+ * @msg: the error message
+ * @str1: extra data
+ * @str2: extra data
+ *
+ * Handle a validation error
+ */
+static void
+xmlErrValid(xmlParserCtxtPtr ctxt, xmlParserErrors error,
+ const char *msg, const char *str1, const char *str2)
+{
+ 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,
+ (const char *) str2, NULL, 0, 0,
+ msg, (const char *) str1, (const char *) str2);
+ ctxt->valid = 0;
+ } else {
+ __xmlRaiseError(schannel,
+ NULL, NULL,
+ ctxt, NULL, XML_FROM_DTD, error,
+ XML_ERR_ERROR, NULL, 0, (const char *) str1,
+ (const char *) str2, NULL, 0, 0,
+ msg, (const char *) str1, (const char *) str2);
+ }
+}
+
+/**
+ * xmlFatalErrMsg:
+ * @ctxt: an XML parser context
+ * @error: the error number
+ * @msg: the error message
+ * @str1: an error string
+ * @str2: an error string
+ *
+ * Handle a fatal parser error, i.e. violating Well-Formedness constraints
+ */
+static void
+xmlFatalErrMsg(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_PARSER, error,
+ XML_ERR_FATAL, NULL, 0,
+ (const char *) str1, (const char *) str2,
+ NULL, 0, 0, msg, str1, str2);
+ if (ctxt != NULL) {
+ ctxt->wellFormed = 0;
+ ctxt->valid = 0;
+ if (ctxt->recovery == 0)
+ ctxt->disableSAX = 1;
+ }
+}
+
+/**
+ * xmlWarnMsg:
+ * @ctxt: an XML parser context
+ * @error: the error number
+ * @msg: the error message
+ * @str1: an error string
+ * @str2: an error string
+ *
+ * Handle a parser warning
+ */
+static void
+xmlWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
+ const char *msg, const xmlChar *str1)
+{
+ 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_WARNING, NULL, 0,
+ (const char *) str1, NULL,
+ NULL, 0, 0, msg, str1);
+}
+
+/**
+ * xmlNsErrMsg:
+ * @ctxt: an XML parser context
+ * @error: the error number
+ * @msg: the error message
+ * @str1: an error string
+ * @str2: an error string
+ *
+ * Handle a namespace error
+ */
+static void
+xmlNsErrMsg(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_NAMESPACE, error,
+ XML_ERR_ERROR, NULL, 0,
+ (const char *) str1, (const char *) str2,
+ NULL, 0, 0, msg, str1, str2);
+}
+
+/**
+ * xmlNsWarnMsg:
+ * @ctxt: an XML parser context
+ * @error: the error number
+ * @msg: the error message
+ * @str1: an error string
+ *
+ * Handle a namespace warning
+ */
+static void
+xmlNsWarnMsg(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_NAMESPACE, error,
+ XML_ERR_WARNING, NULL, 0,
+ (const char *) str1, (const char *) str2,
+ NULL, 0, 0, msg, str1, str2);
+}
+
+/**
+ * xmlSAX2GetPublicId:
+ * @ctx: the user data (XML parser context)
+ *
+ * Provides the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
+ *
+ * Returns a xmlChar *
+ */
+const xmlChar *
+xmlSAX2GetPublicId(void *ctx ATTRIBUTE_UNUSED)
+{
+ /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
+ return(NULL);
+}
+
+/**
+ * xmlSAX2GetSystemId:
+ * @ctx: the user data (XML parser context)
+ *
+ * Provides the system ID, basically URL or filename e.g.
+ * http://www.sgmlsource.com/dtds/memo.dtd
+ *
+ * Returns a xmlChar *
+ */
+const xmlChar *
+xmlSAX2GetSystemId(void *ctx)
+{
+ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+ if ((ctx == NULL) || (ctxt->input == NULL)) return(NULL);
+ return((const xmlChar *) ctxt->input->filename);
+}
+
+/**
+ * xmlSAX2GetLineNumber:
+ * @ctx: the user data (XML parser context)
+ *
+ * Provide the line number of the current parsing point.
+ *
+ * Returns an int
+ */
+int
+xmlSAX2GetLineNumber(void *ctx)
+{
+ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+ if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
+ return(ctxt->input->line);
+}
+
+/**
+ * xmlSAX2GetColumnNumber:
+ * @ctx: the user data (XML parser context)
+ *
+ * Provide the column number of the current parsing point.
+ *
+ * Returns an int
+ */
+int
+xmlSAX2GetColumnNumber(void *ctx)
+{
+ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+ if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
+ return(ctxt->input->col);
+}
+
+/**
+ * xmlSAX2IsStandalone:
+ * @ctx: the user data (XML parser context)
+ *
+ * Is this document tagged standalone ?
+ *
+ * Returns 1 if true
+ */
+int
+xmlSAX2IsStandalone(void *ctx)
+{
+ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+ if ((ctx == NULL) || (ctxt->myDoc == NULL)) return(0);
+ return(ctxt->myDoc->standalone == 1);
+}
+
+/**
+ * xmlSAX2HasInternalSubset:
+ * @ctx: the user data (XML parser context)
+ *
+ * Does this document has an internal subset
+ *
+ * Returns 1 if true
+ */
+int
+xmlSAX2HasInternalSubset(void *ctx)
+{
+ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+ if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0);
+ return(ctxt->myDoc->intSubset != NULL);
+}
+
+/**
+ * xmlSAX2HasExternalSubset:
+ * @ctx: the user data (XML parser context)
+ *
+ * Does this document has an external subset
+ *
+ * Returns 1 if true
+ */
+int
+xmlSAX2HasExternalSubset(void *ctx)
+{
+ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+ if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0);
+ return(ctxt->myDoc->extSubset != NULL);
+}
+
+/**
+ * xmlSAX2InternalSubset:
+ * @ctx: the user data (XML parser context)
+ * @name: the root element name
+ * @ExternalID: the external ID
+ * @SystemID: the SYSTEM ID (e.g. filename or URL)
+ *
+ * Callback on internal subset declaration.
+ */
+void
+xmlSAX2InternalSubset(void *ctx, const xmlChar *name,
+ const xmlChar *ExternalID, const xmlChar *SystemID)
+{
+ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+ xmlDtdPtr dtd;
+ if (ctx == NULL) return;
+#ifdef DEBUG_SAX
+ xmlGenericError(xmlGenericErrorContext,
+ "SAX.xmlSAX2InternalSubset(%s, %s, %s)\n",
+ name, ExternalID, SystemID);
+#endif
+
+ if (ctxt->myDoc == NULL)
+ return;
+ dtd = xmlGetIntSubset(ctxt->myDoc);
+ if (dtd != NULL) {
+ if (ctxt->html)
+ return;
+ xmlUnlinkNode((xmlNodePtr) dtd);
+ xmlFreeDtd(dtd);
+ ctxt->myDoc->intSubset = NULL;
+ }
+ ctxt->myDoc->intSubset =
+ xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
+ if (ctxt->myDoc->intSubset == NULL)
+ xmlSAX2ErrMemory(ctxt, "xmlSAX2InternalSubset");
+}
+
+/**
+ * xmlSAX2ExternalSubset:
+ * @ctx: the user data (XML parser context)
+ * @name: the root element name
+ * @ExternalID: the external ID
+ * @SystemID: the SYSTEM ID (e.g. filename or URL)
+ *
+ * Callback on external subset declaration.
+ */
+void
+xmlSAX2ExternalSubset(void *ctx, const xmlChar *name,
+ const xmlChar *ExternalID, const xmlChar *SystemID)
+{
+ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+ if (ctx == NULL) return;
+#ifdef DEBUG_SAX
+ xmlGenericError(xmlGenericErrorContext,
+ "SAX.xmlSAX2ExternalSubset(%s, %s, %s)\n",
+ name, ExternalID, SystemID);
+#endif
+ if (((ExternalID != NULL) || (SystemID != NULL)) &&
+ (((ctxt->validate) || (ctxt->loadsubset != 0)) &&
+ (ctxt->wellFormed && ctxt->myDoc))) {
+ /*
+ * Try to fetch and parse the external subset.
+ */
+ xmlParserInputPtr oldinput;
+ int oldinputNr;
+ int oldinputMax;
+ xmlParserInputPtr *oldinputTab;
+ xmlParserInputPtr input = NULL;
+ xmlCharEncoding enc;
+ int oldcharset;
+
+ /*
+ * Ask the Entity resolver to load the damn thing
+ */
+ if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
+ input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
+ SystemID);
+ if (input == NULL) {
+ return;
+ }
+
+ xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
+
+ /*
+ * make sure we won't destroy the main document context
+ */
+ oldinput = ctxt->input;
+ oldinputNr = ctxt->inputNr;
+ oldinputMax = ctxt->inputMax;
+ oldinputTab = ctxt->inputTab;
+ oldcharset = ctxt->charset;
+
+ ctxt->inputTab = (xmlParserInputPtr *)
+ xmlMalloc(5 * sizeof(xmlParserInputPtr));
+ if (ctxt->inputTab == NULL) {
+ xmlSAX2ErrMemory(ctxt, "xmlSAX2ExternalSubset");
+ ctxt->input = oldinput;
+ ctxt->inputNr = oldinputNr;
+ ctxt->inputMax = oldinputMax;
+ ctxt->inputTab = oldinputTab;
+ ctxt->charset = oldcharset;
+ return;
+ }
+ ctxt->inputNr = 0;
+ ctxt->inputMax = 5;
+ ctxt->input = NULL;
+ xmlPushInput(ctxt, input);
+
+ /*
+ * On the fly encoding conversion if needed
+ */
+ if (ctxt->input->length >= 4) {
+ enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
+ xmlSwitchEncoding(ctxt, enc);
+ }
+
+ if (input->filename == NULL)
+ input->filename = (char *) xmlCanonicPath(SystemID);
+ input->line = 1;
+ input->col = 1;
+ input->base = ctxt->input->cur;
+ input->cur = ctxt->input->cur;
+ input->free = NULL;
+
+ /*
+ * let's parse that entity knowing it's an external subset.
+ */
+ xmlParseExternalSubset(ctxt, ExternalID, SystemID);
+
+ /*
+ * Free up the external entities
+ */
+
+ while (ctxt->inputNr > 1)
+ xmlPopInput(ctxt);
+ xmlFreeInputStream(ctxt->input);
+ xmlFree(ctxt->inputTab);
+
+ /*
+ * Restore the parsing context of the main entity
+ */
+ ctxt->input = oldinput;
+ ctxt->inputNr = oldinputNr;
+ ctxt->inputMax = oldinputMax;
+ ctxt->inputTab = oldinputTab;
+ ctxt->charset = oldcharset;
+ /* ctxt->wellFormed = oldwellFormed; */
+ }
+}
+
+/**
+ * xmlSAX2ResolveEntity:
+ * @ctx: the user data (XML parser context)
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ *
+ * The entity loader, to control the loading of external entities,
+ * the application can either:
+ * - override this xmlSAX2ResolveEntity() callback in the SAX block
+ * - or better use the xmlSetExternalEntityLoader() function to
+ * set up it's own entity resolution routine
+ *
+ * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
+ */
+xmlParserInputPtr
+xmlSAX2ResolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
+{
+ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+ xmlParserInputPtr ret;
+ xmlChar *URI;
+ const char *base = NULL;
+
+ if (ctx == NULL) return(NULL);
+ if (ctxt->input != NULL)
+ base = ctxt->input->filename;
+ if (base == NULL)
+ base = ctxt->directory;
+
+ URI = xmlBuildURI(systemId, (const xmlChar *) base);
+
+#ifdef DEBUG_SAX
+ xmlGenericError(xmlGenericErrorContext,
+ "SAX.xmlSAX2ResolveEntity(%s, %s)\n", publicId, systemId);
+#endif
+
+ ret = xmlLoadExternalEntity((const char *) URI,
+ (const char *) publicId, ctxt);
+ if (URI != NULL)
+ xmlFree(URI);
+ return(ret);
+}
+
+/**
+ * xmlSAX2GetEntity:
+ * @ctx: the user data (XML parser context)
+ * @name: The entity name
+ *
+ * Get an entity by name
+ *
+ * Returns the xmlEntityPtr if found.
+ */
+xmlEntityPtr
+xmlSAX2GetEntity(void *ctx, const xmlChar *name)
+{
+ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+ xmlEntityPtr ret = NULL;
+
+ if (ctx == NULL) return(NULL);
+#ifdef DEBUG_SAX
+ xmlGenericError(xmlGenericErrorContext,
+ "SAX.xmlSAX2GetEntity(%s)\n", name);
+#endif
+
+ if (ctxt->inSubset == 0) {
+ ret = xmlGetPredefinedEntity(name);
+ if (ret != NULL)
+ return(ret);
+ }
+ if ((ctxt->myDoc != NULL) && (ctxt->myDoc->standalone == 1)) {
+ if (ctxt->inSubset == 2) {
+ ctxt->myDoc->standalone = 0;
+ ret = xmlGetDocEntity(ctxt->myDoc, name);
+ ctxt->myDoc->standalone = 1;
+ } else {
+ ret = xmlGetDocEntity(ctxt->myDoc, name);
+ if (ret == NULL) {
+ ctxt->myDoc->standalone = 0;
+ ret = xmlGetDocEntity(ctxt->myDoc, name);
+ if (ret != NULL) {
+ xmlFatalErrMsg(ctxt, XML_ERR_NOT_STANDALONE,
+ "Entity(%s) document marked standalone but requires external subset\n",
+ name, NULL);
+ }
+ ctxt->myDoc->standalone = 1;
+ }
+ }
+ } else {
+ ret = xmlGetDocEntity(ctxt->myDoc, name);
+ }
+ if ((ret != NULL) &&
+ ((ctxt->validate) || (ctxt->replaceEntities)) &&
+ (ret->children == NULL) &&
+ (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
+ int val;
+
+ /*
+ * for validation purposes we really need to fetch and
+ * parse the external entity
+ */
+ xmlNodePtr children;
+
+ val = xmlParseCtxtExternalEntity(ctxt, ret->URI,
+ ret->ExternalID, &children);
+ if (val == 0) {
+ xmlAddChildList((xmlNodePtr) ret, children);
+ } else {
+ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
+ "Failure to process entity %s\n", name, NULL);
+ ctxt->validate = 0;
+ return(NULL);
+ }
+ ret->owner = 1;
+ ret->checked = 1;
+ }
+ return(ret);
+}
+
+/**
+ * xmlSAX2GetParameterEntity:
+ * @ctx: the user data (XML parser context)
+ * @name: The entity name
+ *
+ * Get a parameter entity by name
+ *
+ * Returns the xmlEntityPtr if found.
+ */
+xmlEntityPtr
+xmlSAX2GetParameterEntity(void *ctx, const xmlChar *name)
+{
+ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+ xmlEntityPtr ret;
+
+ if (ctx == NULL) return(NULL);
+#ifdef DEBUG_SAX
+ xmlGenericError(xmlGenericErrorContext,
+ "SAX.xmlSAX2GetParameterEntity(%s)\n", name);
+#endif
+
+ ret = xmlGetParameterEntity(ctxt->myDoc, name);
+ return(ret);
+}
+
+
+/**
+ * xmlSAX2EntityDecl:
+ * @ctx: the user data (XML parser context)
+ * @name: the entity name
+ * @type: the entity type
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ * @content: the entity value (without processing).
+ *
+ * An entity definition has been parsed
+ */
+void
+xmlSAX2EntityDecl(void *ctx, const xmlChar *name, int type,
+ const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
+{
+ xmlEntityPtr ent;
+ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+
+ if (ctx == NULL) return;
+#ifdef DEBUG_SAX
+ xmlGenericError(xmlGenericErrorContext,
+ "SAX.xmlSAX2EntityDecl(%s, %d, %s, %s, %s)\n",
+ name, type, publicId, systemId, content);
+#endif
+ if (ctxt->inSubset == 1) {
+ ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
+ systemId, content);
+ if ((ent == NULL) && (ctxt->pedantic))
+ xmlWarnMsg(ctxt, XML_WAR_ENTITY_REDEFINED,
+ "Entity(%s) already defined in the internal subset\n",
+ name);
+ if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
+ xmlChar *URI;
+ const char *base = NULL;
+
+ if (ctxt->input != NULL)
+ base = ctxt->input->filename;
+ if (base == NULL)
+ base = ctxt->directory;
+
+ URI = xmlBuildURI(systemId, (const xmlChar *) base);
+ ent->URI = URI;
+ }
+ } else if (ctxt->inSubset == 2) {
+ ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
+ systemId, content);
+ if ((ent == NULL) && (ctxt->pedantic) &&
+ (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
+ ctxt->sax->warning(ctxt->userData,
+ "Entity(%s) already defined in the external subset\n", name);
+ if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
+ xmlChar *URI;
+ const char *base = NULL;
+
+ if (ctxt->input != NULL)
+ base = ctxt->input->filename;
+ if (base == NULL)
+ base = ctxt->directory;
+
+ URI = xmlBuildURI(systemId, (const xmlChar *) base);
+ ent->URI = URI;
+ }
+ } else {
+ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
+ "SAX.xmlSAX2EntityDecl(%s) called while not in subset\n",
+ name, NULL);
+ }
+}
+
+/**
+ * xmlSAX2AttributeDecl:
+ * @ctx: the user data (XML parser context)
+ * @elem: the name of the element
+ * @fullname: the attribute name
+ * @type: the attribute type
+ * @def: the type of default value
+ * @defaultValue: the attribute default value
+ * @tree: the tree of enumerated value set
+ *
+ * An attribute definition has been parsed
+ */
+void
+xmlSAX2AttributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
+ int type, int def, const xmlChar *defaultValue,
+ xmlEnumerationPtr tree)
+{
+ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+ xmlAttributePtr attr;
+ xmlChar *name = NULL, *prefix = NULL;
+
+ if ((ctxt == NULL) || (ctxt->myDoc == NULL))
+ return;
+
+#ifdef DEBUG_SAX
+ xmlGenericError(xmlGenericErrorContext,
+ "SAX.xmlSAX2AttributeDecl(%s, %s, %d, %d, %s, ...)\n",
+ elem, fullname, type, def, defaultValue);
+#endif
+ if ((xmlStrEqual(fullname, BAD_CAST "xml:id")) &&
+ (type != XML_ATTRIBUTE_ID)) {
+ /*
+ * Raise the error but keep the validity flag
+ */
+ int tmp = ctxt->valid;
+ xmlErrValid(ctxt, XML_DTD_XMLID_TYPE,
+ "xml:id : attribute type should be ID\n", NULL, NULL);
+ ctxt->valid = tmp;
+ }
+ /* TODO: optimize name/prefix allocation */
+ name = xmlSplitQName(ctxt, fullname, &prefix);
+ ctxt->vctxt.valid = 1;
+ if (ctxt->inSubset == 1)
+ attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
+ name, prefix, (xmlAttributeType) type,
+ (xmlAttributeDefault) def, defaultValue, tree);
+ else if (ctxt->inSubset == 2)
+ attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
+ name, prefix, (xmlAttributeType) type,
+ (xmlAttributeDefault) def, defaultValue, tree);
+ else {
+ xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
+ "SAX.xmlSAX2AttributeDecl(%s) called while not in subset\n",
+ name, NULL);
+ xmlFreeEnumeration(tree);
+ return;
+ }
+#ifdef LIBXML_VALID_ENABLED
+ if (ctxt->vctxt.valid == 0)
+ ctxt->valid = 0;
+ if ((attr != NULL) && (ctxt->validate) && (ctxt->wellFormed) &&
+ (ctxt->myDoc->intSubset != NULL))
+ ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
+ attr);
+#endif /* LIBXML_VALID_ENABLED */
+ if (prefix != NULL)
+ xmlFree(prefix);
+ if (name != NULL)
+ xmlFree(name);
+}
+
+/**
+ * xmlSAX2ElementDecl:
+ * @ctx: the user data (XML parser context)
+ * @name: the element name
+ * @type: the element type
+ * @content: the element value tree
+ *
+ * An element definition has been parsed
+ */
+void
+xmlSAX2ElementDecl(void *ctx, const xmlChar * name, int type,
+ xmlElementContentPtr content)
+{
+ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+ xmlElementPtr elem = NULL;
+
+ if ((ctxt == NULL) || (ctxt->myDoc == NULL))
+ return;
+
+#ifdef DEBUG_SAX
+ xmlGenericError(xmlGenericErrorContext,
+ "SAX.xmlSAX2ElementDecl(%s, %d, ...)\n", name, type);
+#endif
+
+ if (ctxt->inSubset == 1)
+ elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
+ name, (xmlElementTypeVal) type, content);
+ else if (ctxt->inSubset == 2)
+ elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
+ name, (xmlElementTypeVal) type, content);
+ else {
+ xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
+ "SAX.xmlSAX2ElementDecl(%s) called while not in subset\n",
+ name, NULL);
+ return;
+ }
+#ifdef LIBXML_VALID_ENABLED
+ if (elem == NULL)
+ ctxt->valid = 0;
+ if (ctxt->validate && ctxt->wellFormed &&
+ ctxt->myDoc && ctxt->myDoc->intSubset)
+ ctxt->valid &=
+ xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
+#endif /* LIBXML_VALID_ENABLED */
+}
+
+/**
+ * xmlSAX2NotationDecl:
+ * @ctx: the user data (XML parser context)
+ * @name: The name of the notation
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ *
+ * What to do when a notation declaration has been parsed.
+ */
+void
+xmlSAX2NotationDecl(void *ctx, const xmlChar *name,
+ const xmlChar *publicId, const xmlChar *systemId)
+{
+ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+ xmlNotationPtr nota = NULL;
+
+ if ((ctxt == NULL) || (ctxt->myDoc == NULL))
+ return;
+
+#ifdef DEBUG_SAX
+ xmlGenericError(xmlGenericErrorContext,
+ "SAX.xmlSAX2NotationDecl(%s, %s, %s)\n", name, publicId, systemId);
+#endif
+
+ if ((publicId == NULL) && (systemId == NULL)) {
+ xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING,
+ "SAX.xmlSAX2NotationDecl(%s) externalID or PublicID missing\n",
+ name, NULL);
+ return;
+ } else if (ctxt->inSubset == 1)
+ nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
+ publicId, systemId);
+ else if (ctxt->inSubset == 2)
+ nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, name,
+ publicId, systemId);
+ else {
+ xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING,
+ "SAX.xmlSAX2NotationDecl(%s) called while not in subset\n",
+ name, NULL);
+ return;
+ }
+#ifdef LIBXML_VALID_ENABLED
+ if (nota == NULL) ctxt->valid = 0;
+ if ((ctxt->validate) && (ctxt->wellFormed) &&
+ (ctxt->myDoc->intSubset != NULL))
+ ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
+ nota);
+#endif /* LIBXML_VALID_ENABLED */
+}
+
+/**
+ * xmlSAX2UnparsedEntityDecl:
+ * @ctx: the user data (XML parser context)
+ * @name: The name of the entity
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ * @notationName: the name of the notation
+ *
+ * What to do when an unparsed entity declaration is parsed
+ */
+void
+xmlSAX2UnparsedEntityDecl(void *ctx, const xmlChar *name,
+ const xmlChar *publicId, const xmlChar *systemId,
+ const xmlChar *notationName)
+{
+ xmlEntityPtr ent;
+ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+ if (ctx == NULL) return;
+#ifdef DEBUG_SAX
+ xmlGenericError(xmlGenericErrorContext,
+ "SAX.xmlSAX2UnparsedEntityDecl(%s, %s, %s, %s)\n",
+ name, publicId, systemId, notationName);
+#endif
+ if (ctxt->inSubset == 1) {
+ ent = xmlAddDocEntity(ctxt->myDoc, name,
+ XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
+ publicId, systemId, notationName);
+ if ((ent == NULL) && (ctxt->pedantic) &&
+ (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
+ ctxt->sax->warning(ctxt->userData,
+ "Entity(%s) already defined in the internal subset\n", name);
+ if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
+ xmlChar *URI;
+ const char *base = NULL;
+
+ if (ctxt->input != NULL)
+ base = ctxt->input->filename;
+ if (base == NULL)
+ base = ctxt->directory;
+
+ URI = xmlBuildURI(systemId, (const xmlChar *) base);
+ ent->URI = URI;
+ }
+ } else if (ctxt->inSubset == 2) {
+ ent = xmlAddDtdEntity(ctxt->myDoc, name,
+ XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
+ publicId, systemId, notationName);
+ if ((ent == NULL) && (ctxt->pedantic) &&
+ (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
+ ctxt->sax->warning(ctxt->userData,
+ "Entity(%s) already defined in the external subset\n", name);
+ if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
+ xmlChar *URI;
+ const char *base = NULL;
+
+ if (ctxt->input != NULL)
+ base = ctxt->input->filename;
+ if (base == NULL)
+ base = ctxt->directory;
+
+ URI = xmlBuildURI(systemId, (const xmlChar *) base);
+ ent->URI = URI;
+ }
+ } else {
+ xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
+ "SAX.xmlSAX2UnparsedEntityDecl(%s) called while not in subset\n",
+ name, NULL);
+ }
+}
+
+/**
+ * xmlSAX2SetDocumentLocator:
+ * @ctx: the user data (XML parser context)
+ * @loc: A SAX Locator
+ *
+ * Receive the document locator at startup, actually xmlDefaultSAXLocator
+ * Everything is available on the context, so this is useless in our case.
+ */
+void
+xmlSAX2SetDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
+{
+ /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
+#ifdef DEBUG_SAX
+ xmlGenericError(xmlGenericErrorContext,
+ "SAX.xmlSAX2SetDocumentLocator()\n");
+#endif
+}
+
+/**
+ * xmlSAX2StartDocument:
+ * @ctx: the user data (XML parser context)
+ *
+ * called when the document start being processed.
+ */
+void
+xmlSAX2StartDocument(void *ctx)
+{
+ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+ xmlDocPtr doc;
+
+ if (ctx == NULL) return;
+
+#ifdef DEBUG_SAX
+ xmlGenericError(xmlGenericErrorContext,
+ "SAX.xmlSAX2StartDocument()\n");
+#endif
+ if (ctxt->html) {
+#ifdef LIBXML_HTML_ENABLED
+ if (ctxt->myDoc == NULL)
+ ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
+ if (ctxt->myDoc == NULL) {
+ xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
+ return;
+ }
+#else
+ xmlGenericError(xmlGenericErrorContext,
+ "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 = xmlNewDoc(ctxt->version);
+ if (doc != NULL) {
+ if (ctxt->encoding != NULL)
+ doc->encoding = xmlStrdup(ctxt->encoding);
+ else
+ doc->encoding = NULL;
+ doc->standalone = ctxt->standalone;
+ } else {
+ xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
+ return;
+ }
+ if ((ctxt->dictNames) && (doc != NULL)) {
+ doc->dict = ctxt->dict;
+ xmlDictReference(doc->dict);
+ }
+ }
+ if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
+ (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
+ ctxt->myDoc->URL = xmlPathToURI((const xmlChar *)ctxt->input->filename);
+ if (ctxt->myDoc->URL == NULL)
+ xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
+ }
+}
+
+/**
+ * xmlSAX2EndDocument:
+ * @ctx: the user data (XML parser context)
+ *
+ * called when the document end has been detected.
+ */
+void
+xmlSAX2EndDocument(void *ctx)
+{
+ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+#ifdef DEBUG_SAX
+ xmlGenericError(xmlGenericErrorContext,
+ "SAX.xmlSAX2EndDocument()\n");
+#endif
+ if (ctx == NULL) return;
+#ifdef LIBXML_VALID_ENABLED
+ if (ctxt->validate && ctxt->wellFormed &&
+ ctxt->myDoc && ctxt->myDoc->intSubset)
+ ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
+#endif /* LIBXML_VALID_ENABLED */
+
+ /*
+ * Grab the encoding if it was added on-the-fly
+ */
+ if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
+ (ctxt->myDoc->encoding == NULL)) {
+ ctxt->myDoc->encoding = ctxt->encoding;
+ ctxt->encoding = NULL;
+ }
+ if ((ctxt->inputTab != NULL) &&
+ (ctxt->inputNr > 0) && (ctxt->inputTab[0] != NULL) &&
+ (ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
+ (ctxt->myDoc->encoding == NULL)) {
+ ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
+ }
+ if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
+ (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
+ ctxt->myDoc->charset = ctxt->charset;
+ }
+}
+
+#if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_DOCB_ENABLED)
+/**
+ * xmlSAX2AttributeInternal:
+ * @ctx: the user data (XML parser context)
+ * @fullname: The attribute name, including namespace prefix
+ * @value: The attribute value
+ * @prefix: the prefix on the element node
+ *
+ * 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
+xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
+ const xmlChar *value, const xmlChar *prefix ATTRIBUTE_UNUSED)
+{
+ xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+ xmlAttrPtr ret;
+ xmlChar *name;
+ xmlChar *ns;
+ xmlChar *nval;
+ xmlNsPtr namespace;
+
+ /*
+ * Split the full name into a namespace prefix and the tag name
+ */
+ name = xmlSplitQName(ctxt, fullname, &ns);
+ if ((name != NULL) && (name[0] == 0)) {
+ if (xmlStrEqual(ns, BAD_CAST "xmlns")) {
+ xmlNsErrMsg(ctxt, XML_ERR_NS_DECL_ERROR,
+ "invalid namespace declaration '%s'\n",
+ fullname, NULL);
+ } else {
+ xmlNsWarnMsg(ctxt, XML_WAR_NS_COLUMN,
+ "Avoid attribute ending with ':' like '%s'\n",
+ fullname, NULL);
+ }
+ if (ns != NULL)
+ xmlFree(ns);
+ ns = NULL;
+ xmlFree(name);
+ name = xmlStrdup(fullname);
+ }
+ if (name == NULL) {
+ xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
+ if (ns != NULL)
+ xmlFree(ns);
+ return;
+ }
+
+#ifdef LIBXML_VALID_ENABLED
+ /*
+ * Do the last stage of the attribute normalization
+ * Needed for HTML too:
+ * http://www.w3.org/TR/html4/types.html#h-6.2
+ */
+ ctxt->vctxt.valid = 1;
+ nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt,
+ ctxt->myDoc, ctxt->node,
+ fullname, value);
+ if (ctxt->vctxt.valid != 1) {
+ ctxt->valid = 0;
+ }
+ if (nval != NULL)
+ value = nval;
+#else
+ nval = NULL;
+#endif /* LIBXML_VALID_ENABLED */
+
+ /*
+ * Check whether it's a namespace definition
+ */
+ if ((!ctxt->html) && (ns == NULL) &&
+ (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
+ (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
+ xmlNsPtr nsret;
+ xmlChar *val;
+
+ if (!ctxt->replaceEntities) {
+ ctxt->depth++;
+ val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
+ 0,0,0);
+ ctxt->depth--;
+ } else {
+ val = (xmlChar *) value;
+ }
+
+ if (val[0] != 0) {
+ xmlURIPtr uri;
+
+ uri = xmlParseURI((const char *)val);
+ if (uri == NULL) {
+ if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
+ ctxt->sax->warning(ctxt->userData,
+ "xmlns: %s not a valid URI\n", val);
+ } else {
+ if (uri->scheme == NULL) {
+ if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
+ ctxt->sax->warning(ctxt->userData,
+ "xmlns: URI %s is not absolute\n", val);
+ }
+ xmlFreeURI(uri);
+ }
+ }
+
+ /* a default namespace definition */
+ nsret = xmlNewNs(ctxt->node, val, NULL);
+
+#ifdef LIBXML_VALID_ENABLED
+ /*
+ * Validate also for namespace decls, they are attributes from
+ * an XML-1.0 perspective
+ */
+ if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
+ ctxt->myDoc && ctxt->myDoc->intSubset)
+ ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
+ ctxt->node, prefix, nsret, val);
+#endif /* LIBXML_VALID_ENABLED */
+ if (name != NULL)
+ xmlFree(name);
+ if (nval != NULL)
+ xmlFree(nval);
+ if (val != value)
+ xmlFree(val);
+ return;
+ }
+ if ((!ctxt->html) &&
+ (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
+ (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
+ xmlNsPtr nsret;
+ xmlChar *val;
+
+ if (!ctxt->replaceEntities) {
+ ctxt->depth++;
+ val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
+ 0,0,0);
+ ctxt->depth--;
+ if (val == NULL) {
+ xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
+ xmlFree(ns);
+ if (name != NULL)
+ xmlFree(name);
+ return;
+ }
+ } else {
+ val = (xmlChar *) value;
+ }
+
+ if (val[0] == 0) {
+ xmlNsErrMsg(ctxt, XML_NS_ERR_EMPTY,
+ "Empty namespace name for prefix %s\n", name, NULL);
+ }
+ if ((ctxt->pedantic != 0) && (val[0] != 0)) {
+ xmlURIPtr uri;
+
+ uri = xmlParseURI((const char *)val);
+ if (uri == NULL) {
+ xmlNsWarnMsg(ctxt, XML_WAR_NS_URI,
+ "xmlns:%s: %s not a valid URI\n", name, value);
+ } else {
+ if (uri->scheme == NULL) {
+ xmlNsWarnMsg(ctxt, XML_WAR_NS_URI_RELATIVE,
+ "xmlns:%s: URI %s is not absolute\n", name, value);
+ }
+ xmlFreeURI(uri);
+ }
+ }
+
+ /* a standard namespace definition */
+ nsret = xmlNewNs(ctxt->node, val, name);
+ xmlFree(ns);
+#ifdef LIBXML_VALID_ENABLED
+ /*
+ * Validate also for namespace decls, they are attributes from
+ * an XML-1.0 perspective
+ */
+ if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
+ ctxt->myDoc && ctxt->myDoc->intSubset)
+ ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
+ ctxt->node, prefix, nsret, value);
+#endif /* LIBXML_VALID_ENABLED */
+ if (name != NULL)
+ xmlFree(name);
+ if (nval != NULL)
+ xmlFree(nval);
+ if (val != value)
+ xmlFree(val);
+ return;
+ }
+
+ if (ns != NULL) {
+ xmlAttrPtr prop;
+ namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
+ if (namespace == NULL) {
+ xmlNsErrMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
+ "Namespace prefix %s of attribute %s is not defined\n",
+ ns, name);
+ }
+
+ prop = ctxt->node->properties;
+ while (prop != NULL) {
+ if (prop->ns != NULL) {
+ if ((xmlStrEqual(name, prop->name)) &&
+ ((namespace == prop->ns) ||
+ (xmlStrEqual(namespace->href, prop->ns->href)))) {
+ xmlNsErrMsg(ctxt, XML_ERR_ATTRIBUTE_REDEFINED,
+ "Attribute %s in %s redefined\n",
+ name, namespace->href);
+ ctxt->wellFormed = 0;
+ if (ctxt->recovery == 0) ctxt->disableSAX = 1;
+ goto error;
+ }
+ }
+ prop = prop->next;
+ }
+ } else {
+ namespace = NULL;
+ }
+
+ /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
+ 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 <stdio.h>
+#include <stdlib.h>
+#include <libxml/xmlversion.h>
+#include <libxml/parser.h>
+#include <libxml/xlink.h>
+
+#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 <aleksey@aleksey.com>
+ */
+#define IN_LIBXML
+#include "libxml.h"
+#ifdef LIBXML_C14N_ENABLED
+#ifdef LIBXML_OUTPUT_ENABLED
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/uri.h>
+#include <libxml/xmlerror.h>
+#include <libxml/globals.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/c14n.h>
+
+/************************************************************************
+ * *
+ * 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, "</");
+ 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);
+ 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 &amp;, all open angle brackets (<) are replaced by &lt;, all closing
+ * angle brackets (>) are replaced by &gt;, and all #xD characters are
+ * replaced by &#xD;.
+ */
+ /* 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 (<?), the PI target name of the node,
+ * a leading space and the string value if it is not empty, and
+ * the closing 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, "\x0A<?");
+ } else {
+ xmlOutputBufferWriteString(ctx->buf, "<?");
+ }
+
+ xmlOutputBufferWriteString(ctx->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 (<!--), the string value of the node, and the
+ * closing 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<!--");
+ } else {
+ xmlOutputBufferWriteString(ctx->buf, "<!--");
+ }
+
+ if (cur->content != NULL) {
+ xmlChar *buffer;
+
+ /* todo: do we need to normalize comment? */
+ buffer = xmlC11NNormalizeComment(cur->content);
+ if (buffer != NULL) {
+ xmlOutputBufferWriteString(ctx->buf,
+ (const char *) buffer);
+ xmlFree(buffer);
+ } else {
+ xmlC14NErrInternal("normalizing comment node");
+ return (-1);
+ }
+ }
+
+ if (ctx->pos == XMLC14N_BEFORE_DOCUMENT_ELEMENT) {
+ xmlOutputBufferWriteString(ctx->buf, "-->\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 <aleksey@aleksey.com>
+ */
+#ifndef __XML_C14N_H__
+#define __XML_C14N_H__
+#ifdef LIBXML_C14N_ENABLED
+#ifdef LIBXML_OUTPUT_ENABLED
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <libxml/xmlversion.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+
+/*
+ * 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 <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/hash.h>
+#include <libxml/uri.h>
+#include <libxml/parserInternals.h>
+#include <libxml/catalog.h>
+#include <libxml/xmlerror.h>
+#include <libxml/threads.h>
+#include <libxml/globals.h>
+
+#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 <richard@cogsci.ed.ac.uk>
+ *> 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 <stdio.h>
+
+#include <libxml/xmlversion.h>
+#include <libxml/xmlstring.h>
+#include <libxml/tree.h>
+
+#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 <wbrack@mmm.com.hk>
+ */
+
+#define IN_LIBXML
+#include "libxml.h"
+#include <libxml/chvalid.h>
+
+/*
+ * 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 <wbrack@mmm.com.hk>
+ */
+
+#ifndef __XML_CHVALID_H__
+#define __XML_CHVALID_H__
+
+#include <libxml/xmlversion.h>
+#include <libxml/xmlstring.h>
+
+#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 <daniel@veillard.com>
+ */
+
+#define IN_LIBXML
+#include "libxml.h"
+#ifdef LIBXML_DEBUG_ENABLED
+
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#include <libxml/xmlmemory.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/valid.h>
+#include <libxml/debugXML.h>
+#include <libxml/HTMLtree.h>
+#include <libxml/HTMLparser.h>
+#include <libxml/xmlerror.h>
+#include <libxml/globals.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/uri.h>
+#ifdef LIBXML_SCHEMAS_ENABLED
+#include <libxml/relaxng.h>
+#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 <stdio.h>
+#include <libxml/xmlversion.h>
+#include <libxml/tree.h>
+
+#ifdef LIBXML_DEBUG_ENABLED
+
+#include <libxml/xpath.h>
+
+#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 <string.h>
+#include <libxml/tree.h>
+#include <libxml/dict.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/xmlerror.h>
+#include <libxml/globals.h>
+
+#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 <libxml/xmlversion.h>
+#include <libxml/tree.h>
+
+#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
--- /dev/null
+++ b/gettext-tools/gnulib-lib/libxml/elfgcchack.h
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" <duerst@w3.org>
+ */
+
+#define IN_LIBXML
+#include "libxml.h"
+
+#include <string.h>
+
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef LIBXML_ICONV_ENABLED
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#endif
+#include <libxml/encoding.h>
+#include <libxml/xmlmemory.h>
+#ifdef LIBXML_HTML_ENABLED
+#include <libxml/HTMLparser.h>
+#endif
+#include <libxml/globals.h>
+#include <libxml/xmlerror.h>
+
+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 '<?xml version="1.0" encoding="UCS4"?>' | 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 <libxml/xmlversion.h>
+
+#ifdef LIBXML_ICONV_ENABLED
+#include <iconv.h>
+#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 <libxml/tree.h>
+#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 <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <libxml/xmlmemory.h>
+#include <libxml/hash.h>
+#include <libxml/entities.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/xmlerror.h>
+#include <libxml/globals.h>
+#include <libxml/dict.h>
+
+/*
+ * 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 <br@sseusa.com> 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 "&quot;", 6);
+ cur++;
+ base = cur;
+ } else if (*cur == '%') {
+ if (base != cur)
+ xmlBufferAdd(buf, base, cur - base);
+ xmlBufferAdd(buf, BAD_CAST "&#x25;", 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, "<!ENTITY ");
+ xmlBufferWriteCHAR(buf, ent->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, "<!ENTITY ");
+ xmlBufferWriteCHAR(buf, ent->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, "<!ENTITY ");
+ xmlBufferWriteCHAR(buf, ent->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, "<!ENTITY % ");
+ xmlBufferWriteCHAR(buf, ent->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, "<!ENTITY % ");
+ xmlBufferWriteCHAR(buf, ent->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 <libxml/xmlversion.h>
+#include <libxml/tree.h>
+
+#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 <daniel@veillard.com>
+ */
+
+#define IN_LIBXML
+#include "libxml.h"
+
+#include <string.h>
+#include <stdarg.h>
+#include <libxml/parser.h>
+#include <libxml/xmlerror.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/globals.h>
+
+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 ((n<col) && (n++ < sizeof(content)-2) && (*ctnt != 0)) {
+ if (*(ctnt) != '\t')
+ *(ctnt) = ' ';
+ ctnt++;
+ }
+ *ctnt++ = '^';
+ *ctnt = 0;
+ channel(data ,"%s\n", content);
+}
+
+/**
+ * xmlParserPrintFileContext:
+ * @input: an xmlParserInputPtr input
+ *
+ * Displays current context within the input content for error tracking
+ */
+void
+xmlParserPrintFileContext(xmlParserInputPtr input) {
+ xmlParserPrintFileContextInternal(input, xmlGenericError,
+ xmlGenericErrorContext);
+}
+
+/**
+ * xmlReportError:
+ * @err: the error
+ * @ctx: the parser context or NULL
+ * @str: the formatted error message
+ *
+ * Report an erro with its context, replace the 4 old error/warning
+ * routines.
+ */
+static void
+xmlReportError(xmlErrorPtr err, xmlParserCtxtPtr ctxt, const char *str,
+ xmlGenericErrorFunc channel, void *data)
+{
+ char *file = NULL;
+ int line = 0;
+ int code = -1;
+ int domain;
+ const xmlChar *name = NULL;
+ xmlNodePtr node;
+ xmlErrorLevel level;
+ xmlParserInputPtr input = NULL;
+ xmlParserInputPtr cur = NULL;
+
+ if (err == NULL)
+ return;
+
+ if (channel == NULL) {
+ channel = xmlGenericError;
+ data = xmlGenericErrorContext;
+ }
+ file = err->file;
+ 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 <Gary.Pennington@uk.sun.com>
+ * daniel@veillard.com
+ */
+
+#define IN_LIBXML
+#include "libxml.h"
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+
+#include <libxml/globals.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/threads.h>
+
+/* #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 <libxml/threads.h>
+#include <libxml/globals.h>
+#include <libxml/SAX.h>
+
+#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 <empty/> but <empty></empty>. 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 <Gary.Pennington@uk.sun.com>, Daniel Veillard
+ */
+
+#ifndef __XML_GLOBALS_H
+#define __XML_GLOBALS_H
+
+#include <libxml/xmlversion.h>
+#include <libxml/parser.h>
+#include <libxml/xmlerror.h>
+#include <libxml/SAX.h>
+#include <libxml/SAX2.h>
+#include <libxml/xmlmemory.h>
+
+#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 <libxml/threads.h>
+#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 <string.h>
+#include <libxml/parser.h>
+#include <libxml/hash.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/xmlerror.h>
+#include <libxml/globals.h>
+
+#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 <bjorn.reese@systematic.dk>
+ */
+
+#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 <libxml/xmlversion.h>
+#include <libxml/parser.h>
+#include <libxml/dict.h>
+
+#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 <string.h>
+
+#include <libxml/tree.h>
+#include <libxml/entities.h>
+#include <libxml/SAX.h>
+#include <libxml/parserInternals.h>
+#include <libxml/HTMLparser.h>
+
+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 '<?namespace ...' constructs.
+ *
+ * This is what the older xml-name Working Draft specified, a bunch of
+ * other stuff may still rely on it, so support is still here as
+ * if it was declared on the root of the Tree:-(
+ *
+ * TODO: remove from library
+ *
+ * To be removed at next drop of binary compatibility
+ */
+
+void
+xmlParseNamespace(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED)
+{
+ static int deprecated = 0;
+
+ if (!deprecated) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlParseNamespace() deprecated function reached\n");
+ deprecated = 1;
+ }
+}
+
+/**
+ * xmlScanName:
+ * @ctxt: an XML parser context
+ *
+ * Trickery: parse an XML name but without consuming the input flow
+ * Needed for rollback cases. Used only when parsing entities references.
+ *
+ * TODO: seems deprecated now, only used in the default part of
+ * xmlParserHandleReference
+ *
+ * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
+ * CombiningChar | Extender
+ *
+ * [5] Name ::= (Letter | '_' | ':') (NameChar)*
+ *
+ * [6] Names ::= Name (S Name)*
+ *
+ * Returns the Name parsed or NULL
+ */
+
+xmlChar *
+xmlScanName(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED)
+{
+ static int deprecated = 0;
+
+ if (!deprecated) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlScanName() deprecated function reached\n");
+ deprecated = 1;
+ }
+ return (NULL);
+}
+
+/**
+ * xmlParserHandleReference:
+ * @ctxt: the parser context
+ *
+ * TODO: Remove, now deprecated ... the test is done directly in the
+ * content parsing
+ * routines.
+ *
+ * [67] Reference ::= EntityRef | CharRef
+ *
+ * [68] EntityRef ::= '&' Name ';'
+ *
+ * [ WFC: Entity Declared ]
+ * the Name given in the entity reference must match that in an entity
+ * declaration, except that well-formed documents need not declare any
+ * of the following entities: amp, lt, gt, apos, quot.
+ *
+ * [ WFC: Parsed Entity ]
+ * An entity reference must not contain the name of an unparsed entity
+ *
+ * [66] CharRef ::= '&#' [0-9]+ ';' |
+ * '&#x' [0-9a-fA-F]+ ';'
+ *
+ * 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
+ */
+void
+xmlParserHandleReference(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED)
+{
+ static int deprecated = 0;
+
+ if (!deprecated) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlParserHandleReference() deprecated function reached\n");
+ deprecated = 1;
+ }
+
+ return;
+}
+
+/**
+ * xmlHandleEntity:
+ * @ctxt: an XML parser context
+ * @entity: an XML entity pointer.
+ *
+ * Default handling of defined entities, when should we define a new input
+ * stream ? When do we just handle that as a set of chars ?
+ *
+ * OBSOLETE: to be removed at some point.
+ */
+
+void
+xmlHandleEntity(xmlParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
+ xmlEntityPtr entity ATTRIBUTE_UNUSED)
+{
+ static int deprecated = 0;
+
+ if (!deprecated) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlHandleEntity() deprecated function reached\n");
+ deprecated = 1;
+ }
+}
+
+/**
+ * xmlNewGlobalNs:
+ * @doc: the document carrying the namespace
+ * @href: the URI associated
+ * @prefix: the prefix for the namespace
+ *
+ * Creation of a Namespace, the old way using PI and without scoping
+ * DEPRECATED !!!
+ * Returns NULL this functionality had been removed
+ */
+xmlNsPtr
+xmlNewGlobalNs(xmlDocPtr doc ATTRIBUTE_UNUSED,
+ const xmlChar * href ATTRIBUTE_UNUSED,
+ const xmlChar * prefix ATTRIBUTE_UNUSED)
+{
+ static int deprecated = 0;
+
+ if (!deprecated) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlNewGlobalNs() deprecated function reached\n");
+ deprecated = 1;
+ }
+ return (NULL);
+}
+
+/**
+ * xmlUpgradeOldNs:
+ * @doc: a document pointer
+ *
+ * Upgrade old style Namespaces (PI) and move them to the root of the document.
+ * DEPRECATED
+ */
+void
+xmlUpgradeOldNs(xmlDocPtr doc ATTRIBUTE_UNUSED)
+{
+ static int deprecated = 0;
+
+ if (!deprecated) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlUpgradeOldNs() deprecated function reached\n");
+ deprecated = 1;
+ }
+}
+
+/**
+ * xmlEncodeEntities:
+ * @doc: the document containing the string
+ * @input: A string to convert to XML.
+ *
+ * TODO: remove xmlEncodeEntities, once we are not afraid of breaking binary
+ * compatibility
+ *
+ * People must migrate their code to xmlEncodeEntitiesReentrant !
+ * This routine will issue a warning when encountered.
+ *
+ * Returns NULL
+ */
+const xmlChar *
+xmlEncodeEntities(xmlDocPtr doc ATTRIBUTE_UNUSED,
+ const xmlChar * input ATTRIBUTE_UNUSED)
+{
+ static int warning = 1;
+
+ if (warning) {
+ xmlGenericError(xmlGenericErrorContext,
+ "Deprecated API xmlEncodeEntities() used\n");
+ xmlGenericError(xmlGenericErrorContext,
+ " change code to use xmlEncodeEntitiesReentrant()\n");
+ warning = 0;
+ }
+ return (NULL);
+}
+
+/************************************************************************
+ * *
+ * Old set of SAXv1 functions *
+ * *
+ ************************************************************************/
+static int deprecated_v1_msg = 0;
+
+#define DEPRECATED(n) \
+ if (deprecated_v1_msg == 0) \
+ xmlGenericError(xmlGenericErrorContext, \
+ "Use of deprecated SAXv1 function %s\n", n); \
+ deprecated_v1_msg++;
+
+/**
+ * getPublicId:
+ * @ctx: the user data (XML parser context)
+ *
+ * Provides the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
+ * DEPRECATED: use xmlSAX2GetPublicId()
+ *
+ * Returns a xmlChar *
+ */
+const xmlChar *
+getPublicId(void *ctx)
+{
+ DEPRECATED("getPublicId")
+ return (xmlSAX2GetPublicId(ctx));
+}
+
+/**
+ * getSystemId:
+ * @ctx: the user data (XML parser context)
+ *
+ * Provides the system ID, basically URL or filename e.g.
+ * http://www.sgmlsource.com/dtds/memo.dtd
+ * DEPRECATED: use xmlSAX2GetSystemId()
+ *
+ * Returns a xmlChar *
+ */
+const xmlChar *
+getSystemId(void *ctx)
+{
+ DEPRECATED("getSystemId")
+ return (xmlSAX2GetSystemId(ctx));
+}
+
+/**
+ * getLineNumber:
+ * @ctx: the user data (XML parser context)
+ *
+ * Provide the line number of the current parsing point.
+ * DEPRECATED: use xmlSAX2GetLineNumber()
+ *
+ * Returns an int
+ */
+int
+getLineNumber(void *ctx)
+{
+ DEPRECATED("getLineNumber")
+ return (xmlSAX2GetLineNumber(ctx));
+}
+
+/**
+ * getColumnNumber:
+ * @ctx: the user data (XML parser context)
+ *
+ * Provide the column number of the current parsing point.
+ * DEPRECATED: use xmlSAX2GetColumnNumber()
+ *
+ * Returns an int
+ */
+int
+getColumnNumber(void *ctx)
+{
+ DEPRECATED("getColumnNumber")
+ return (xmlSAX2GetColumnNumber(ctx));
+}
+
+/**
+ * isStandalone:
+ * @ctx: the user data (XML parser context)
+ *
+ * Is this document tagged standalone ?
+ * DEPRECATED: use xmlSAX2IsStandalone()
+ *
+ * Returns 1 if true
+ */
+int
+isStandalone(void *ctx)
+{
+ DEPRECATED("isStandalone")
+ return (xmlSAX2IsStandalone(ctx));
+}
+
+/**
+ * hasInternalSubset:
+ * @ctx: the user data (XML parser context)
+ *
+ * Does this document has an internal subset
+ * DEPRECATED: use xmlSAX2HasInternalSubset()
+ *
+ * Returns 1 if true
+ */
+int
+hasInternalSubset(void *ctx)
+{
+ DEPRECATED("hasInternalSubset")
+ return (xmlSAX2HasInternalSubset(ctx));
+}
+
+/**
+ * hasExternalSubset:
+ * @ctx: the user data (XML parser context)
+ *
+ * Does this document has an external subset
+ * DEPRECATED: use xmlSAX2HasExternalSubset()
+ *
+ * Returns 1 if true
+ */
+int
+hasExternalSubset(void *ctx)
+{
+ DEPRECATED("hasExternalSubset")
+ return (xmlSAX2HasExternalSubset(ctx));
+}
+
+/**
+ * internalSubset:
+ * @ctx: the user data (XML parser context)
+ * @name: the root element name
+ * @ExternalID: the external ID
+ * @SystemID: the SYSTEM ID (e.g. filename or URL)
+ *
+ * Callback on internal subset declaration.
+ * DEPRECATED: use xmlSAX2InternalSubset()
+ */
+void
+internalSubset(void *ctx, const xmlChar * name,
+ const xmlChar * ExternalID, const xmlChar * SystemID)
+{
+ DEPRECATED("internalSubset")
+ xmlSAX2InternalSubset(ctx, name, ExternalID, SystemID);
+}
+
+/**
+ * externalSubset:
+ * @ctx: the user data (XML parser context)
+ * @name: the root element name
+ * @ExternalID: the external ID
+ * @SystemID: the SYSTEM ID (e.g. filename or URL)
+ *
+ * Callback on external subset declaration.
+ * DEPRECATED: use xmlSAX2ExternalSubset()
+ */
+void
+externalSubset(void *ctx, const xmlChar * name,
+ const xmlChar * ExternalID, const xmlChar * SystemID)
+{
+ DEPRECATED("externalSubset")
+ xmlSAX2ExternalSubset(ctx, name, ExternalID, SystemID);
+}
+
+/**
+ * resolveEntity:
+ * @ctx: the user data (XML parser context)
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ *
+ * The entity loader, to control the loading of external entities,
+ * the application can either:
+ * - override this resolveEntity() callback in the SAX block
+ * - or better use the xmlSetExternalEntityLoader() function to
+ * set up it's own entity resolution routine
+ * DEPRECATED: use xmlSAX2ResolveEntity()
+ *
+ * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
+ */
+xmlParserInputPtr
+resolveEntity(void *ctx, const xmlChar * publicId,
+ const xmlChar * systemId)
+{
+ DEPRECATED("resolveEntity")
+ return (xmlSAX2ResolveEntity(ctx, publicId, systemId));
+}
+
+/**
+ * getEntity:
+ * @ctx: the user data (XML parser context)
+ * @name: The entity name
+ *
+ * Get an entity by name
+ * DEPRECATED: use xmlSAX2GetEntity()
+ *
+ * Returns the xmlEntityPtr if found.
+ */
+xmlEntityPtr
+getEntity(void *ctx, const xmlChar * name)
+{
+ DEPRECATED("getEntity")
+ return (xmlSAX2GetEntity(ctx, name));
+}
+
+/**
+ * getParameterEntity:
+ * @ctx: the user data (XML parser context)
+ * @name: The entity name
+ *
+ * Get a parameter entity by name
+ * DEPRECATED: use xmlSAX2GetParameterEntity()
+ *
+ * Returns the xmlEntityPtr if found.
+ */
+xmlEntityPtr
+getParameterEntity(void *ctx, const xmlChar * name)
+{
+ DEPRECATED("getParameterEntity")
+ return (xmlSAX2GetParameterEntity(ctx, name));
+}
+
+
+/**
+ * entityDecl:
+ * @ctx: the user data (XML parser context)
+ * @name: the entity name
+ * @type: the entity type
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ * @content: the entity value (without processing).
+ *
+ * An entity definition has been parsed
+ * DEPRECATED: use xmlSAX2EntityDecl()
+ */
+void
+entityDecl(void *ctx, const xmlChar * name, int type,
+ const xmlChar * publicId, const xmlChar * systemId,
+ xmlChar * content)
+{
+ DEPRECATED("entityDecl")
+ xmlSAX2EntityDecl(ctx, name, type, publicId, systemId, content);
+}
+
+/**
+ * attributeDecl:
+ * @ctx: the user data (XML parser context)
+ * @elem: the name of the element
+ * @fullname: the attribute name
+ * @type: the attribute type
+ * @def: the type of default value
+ * @defaultValue: the attribute default value
+ * @tree: the tree of enumerated value set
+ *
+ * An attribute definition has been parsed
+ * DEPRECATED: use xmlSAX2AttributeDecl()
+ */
+void
+attributeDecl(void *ctx, const xmlChar * elem, const xmlChar * fullname,
+ int type, int def, const xmlChar * defaultValue,
+ xmlEnumerationPtr tree)
+{
+ DEPRECATED("attributeDecl")
+ xmlSAX2AttributeDecl(ctx, elem, fullname, type, def, defaultValue,
+ tree);
+}
+
+/**
+ * elementDecl:
+ * @ctx: the user data (XML parser context)
+ * @name: the element name
+ * @type: the element type
+ * @content: the element value tree
+ *
+ * An element definition has been parsed
+ * DEPRECATED: use xmlSAX2ElementDecl()
+ */
+void
+elementDecl(void *ctx, const xmlChar * name, int type,
+ xmlElementContentPtr content)
+{
+ DEPRECATED("elementDecl")
+ xmlSAX2ElementDecl(ctx, name, type, content);
+}
+
+/**
+ * notationDecl:
+ * @ctx: the user data (XML parser context)
+ * @name: The name of the notation
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ *
+ * What to do when a notation declaration has been parsed.
+ * DEPRECATED: use xmlSAX2NotationDecl()
+ */
+void
+notationDecl(void *ctx, const xmlChar * name,
+ const xmlChar * publicId, const xmlChar * systemId)
+{
+ DEPRECATED("notationDecl")
+ xmlSAX2NotationDecl(ctx, name, publicId, systemId);
+}
+
+/**
+ * unparsedEntityDecl:
+ * @ctx: the user data (XML parser context)
+ * @name: The name of the entity
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ * @notationName: the name of the notation
+ *
+ * What to do when an unparsed entity declaration is parsed
+ * DEPRECATED: use xmlSAX2UnparsedEntityDecl()
+ */
+void
+unparsedEntityDecl(void *ctx, const xmlChar * name,
+ const xmlChar * publicId, const xmlChar * systemId,
+ const xmlChar * notationName)
+{
+ DEPRECATED("unparsedEntityDecl")
+ xmlSAX2UnparsedEntityDecl(ctx, name, publicId, systemId,
+ notationName);
+}
+
+/**
+ * setDocumentLocator:
+ * @ctx: the user data (XML parser context)
+ * @loc: A SAX Locator
+ *
+ * Receive the document locator at startup, actually xmlDefaultSAXLocator
+ * Everything is available on the context, so this is useless in our case.
+ * DEPRECATED
+ */
+void
+setDocumentLocator(void *ctx ATTRIBUTE_UNUSED,
+ xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
+{
+ DEPRECATED("setDocumentLocator")
+}
+
+/**
+ * startDocument:
+ * @ctx: the user data (XML parser context)
+ *
+ * called when the document start being processed.
+ * DEPRECATED: use xmlSAX2StartDocument()
+ */
+void
+startDocument(void *ctx)
+{
+ /* don't be too painful for glade users */
+ /* DEPRECATED("startDocument") */
+ xmlSAX2StartDocument(ctx);
+}
+
+/**
+ * endDocument:
+ * @ctx: the user data (XML parser context)
+ *
+ * called when the document end has been detected.
+ * DEPRECATED: use xmlSAX2EndDocument()
+ */
+void
+endDocument(void *ctx)
+{
+ DEPRECATED("endDocument")
+ xmlSAX2EndDocument(ctx);
+}
+
+/**
+ * attribute:
+ * @ctx: the user data (XML parser context)
+ * @fullname: The attribute name, including namespace prefix
+ * @value: 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.
+ * DEPRECATED: use xmlSAX2Attribute()
+ */
+void
+attribute(void *ctx ATTRIBUTE_UNUSED,
+ const xmlChar * fullname ATTRIBUTE_UNUSED,
+ const xmlChar * value ATTRIBUTE_UNUSED)
+{
+ DEPRECATED("attribute")
+}
+
+/**
+ * startElement:
+ * @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.
+ * DEPRECATED: use xmlSAX2StartElement()
+ */
+void
+startElement(void *ctx, const xmlChar * fullname, const xmlChar ** atts)
+{
+ xmlSAX2StartElement(ctx, fullname, atts);
+}
+
+/**
+ * endElement:
+ * @ctx: the user data (XML parser context)
+ * @name: The element name
+ *
+ * called when the end of an element has been detected.
+ * DEPRECATED: use xmlSAX2EndElement()
+ */
+void
+endElement(void *ctx, const xmlChar * name ATTRIBUTE_UNUSED)
+{
+ DEPRECATED("endElement")
+ xmlSAX2EndElement(ctx, name);
+}
+
+/**
+ * reference:
+ * @ctx: the user data (XML parser context)
+ * @name: The entity name
+ *
+ * called when an entity reference is detected.
+ * DEPRECATED: use xmlSAX2Reference()
+ */
+void
+reference(void *ctx, const xmlChar * name)
+{
+ DEPRECATED("reference")
+ xmlSAX2Reference(ctx, name);
+}
+
+/**
+ * characters:
+ * @ctx: the user data (XML parser context)
+ * @ch: a xmlChar string
+ * @len: the number of xmlChar
+ *
+ * receiving some chars from the parser.
+ * DEPRECATED: use xmlSAX2Characters()
+ */
+void
+characters(void *ctx, const xmlChar * ch, int len)
+{
+ DEPRECATED("characters")
+ xmlSAX2Characters(ctx, ch, len);
+}
+
+/**
+ * ignorableWhitespace:
+ * @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 characters
+ * DEPRECATED: use xmlSAX2IgnorableWhitespace()
+ */
+void
+ignorableWhitespace(void *ctx ATTRIBUTE_UNUSED,
+ const xmlChar * ch ATTRIBUTE_UNUSED,
+ int len ATTRIBUTE_UNUSED)
+{
+ DEPRECATED("ignorableWhitespace")
+}
+
+/**
+ * processingInstruction:
+ * @ctx: the user data (XML parser context)
+ * @target: the target name
+ * @data: the PI data's
+ *
+ * A processing instruction has been parsed.
+ * DEPRECATED: use xmlSAX2ProcessingInstruction()
+ */
+void
+processingInstruction(void *ctx, const xmlChar * target,
+ const xmlChar * data)
+{
+ DEPRECATED("processingInstruction")
+ xmlSAX2ProcessingInstruction(ctx, target, data);
+}
+
+/**
+ * globalNamespace:
+ * @ctx: the user data (XML parser context)
+ * @href: the namespace associated URN
+ * @prefix: the namespace prefix
+ *
+ * An old global namespace has been parsed.
+ * DEPRECATED
+ */
+void
+globalNamespace(void *ctx ATTRIBUTE_UNUSED,
+ const xmlChar * href ATTRIBUTE_UNUSED,
+ const xmlChar * prefix ATTRIBUTE_UNUSED)
+{
+ DEPRECATED("globalNamespace")
+}
+
+/**
+ * setNamespace:
+ * @ctx: the user data (XML parser context)
+ * @name: the namespace prefix
+ *
+ * Set the current element namespace.
+ * DEPRECATED
+ */
+
+void
+setNamespace(void *ctx ATTRIBUTE_UNUSED,
+ const xmlChar * name ATTRIBUTE_UNUSED)
+{
+ DEPRECATED("setNamespace")
+}
+
+/**
+ * getNamespace:
+ * @ctx: the user data (XML parser context)
+ *
+ * Get the current element namespace.
+ * DEPRECATED
+ *
+ * Returns the xmlNsPtr or NULL if none
+ */
+
+xmlNsPtr
+getNamespace(void *ctx ATTRIBUTE_UNUSED)
+{
+ DEPRECATED("getNamespace")
+ return (NULL);
+}
+
+/**
+ * checkNamespace:
+ * @ctx: the user data (XML parser context)
+ * @namespace: the namespace to check against
+ *
+ * Check that the current element namespace is the same as the
+ * one read upon parsing.
+ * DEPRECATED
+ *
+ * Returns 1 if true 0 otherwise
+ */
+
+int
+checkNamespace(void *ctx ATTRIBUTE_UNUSED,
+ xmlChar * namespace ATTRIBUTE_UNUSED)
+{
+ DEPRECATED("checkNamespace")
+ return (0);
+}
+
+/**
+ * namespaceDecl:
+ * @ctx: the user data (XML parser context)
+ * @href: the namespace associated URN
+ * @prefix: the namespace prefix
+ *
+ * A namespace has been parsed.
+ * DEPRECATED
+ */
+void
+namespaceDecl(void *ctx ATTRIBUTE_UNUSED,
+ const xmlChar * href ATTRIBUTE_UNUSED,
+ const xmlChar * prefix ATTRIBUTE_UNUSED)
+{
+ DEPRECATED("namespaceDecl")
+}
+
+/**
+ * comment:
+ * @ctx: the user data (XML parser context)
+ * @value: the comment content
+ *
+ * A comment has been parsed.
+ * DEPRECATED: use xmlSAX2Comment()
+ */
+void
+comment(void *ctx, const xmlChar * value)
+{
+ DEPRECATED("comment")
+ xmlSAX2Comment(ctx, value);
+}
+
+/**
+ * cdataBlock:
+ * @ctx: the user data (XML parser context)
+ * @value: The pcdata content
+ * @len: the block length
+ *
+ * called when a pcdata block has been parsed
+ * DEPRECATED: use xmlSAX2CDataBlock()
+ */
+void
+cdataBlock(void *ctx, const xmlChar * value, int len)
+{
+ DEPRECATED("cdataBlock")
+ xmlSAX2CDataBlock(ctx, value, len);
+}
+#define bottom_legacy
+#include "elfgcchack.h"
+#endif /* LIBXML_LEGACY_ENABLED */
+
diff --git a/gettext-tools/gnulib-lib/libxml/libxml.h b/gettext-tools/gnulib-lib/libxml/libxml.h
new file mode 100644
index 0000000..696be62
--- /dev/null
+++ b/gettext-tools/gnulib-lib/libxml/libxml.h
@@ -0,0 +1,79 @@
+/*
+ * libxml.h: internal header only used during the compilation of libxml
+ *
+ * See COPYRIGHT for the status of this software
+ *
+ * Author: breese@users.sourceforge.net
+ */
+
+#ifndef __XML_LIBXML_H__
+#define __XML_LIBXML_H__
+
+#ifndef NO_LARGEFILE_SOURCE
+#ifndef _LARGEFILE_SOURCE
+#define _LARGEFILE_SOURCE
+#endif
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64
+#endif
+#endif
+
+#if defined(macintosh)
+#include "config-mac.h"
+#else
+#include "config.h"
+#include <libxml/xmlversion.h>
+#endif
+
+#if defined(__Lynx__)
+#include <stdio.h> /* pull definition of size_t */
+#include <varargs.h>
+int snprintf(char *, size_t, const char *, ...);
+int vfprintf(FILE *, const char *, va_list);
+#endif
+
+#ifndef WITH_TRIO
+#include <stdio.h>
+#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 <stdlib.h>
+#include <string.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/list.h>
+#include <libxml/globals.h>
+
+/*
+ * 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 <Gary.Pennington@uk.sun.com>
+ */
+
+#ifndef __XML_LINK_INCLUDE__
+#define __XML_LINK_INCLUDE__
+
+#include <libxml/xmlversion.h>
+
+#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 <string.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/xmlerror.h>
+#include <libxml/uri.h>
+#include <libxml/nanoftp.h>
+#include <libxml/globals.h>
+
+/* #define DEBUG_FTP 1 */
+#ifdef STANDALONE
+#ifndef DEBUG_FTP
+#define DEBUG_FTP 1
+#endif
+#endif
+
+
+#ifdef __MINGW32__
+#define _WINSOCKAPI_
+#include <wsockcompat.h>
+#include <winsock2.h>
+#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 <stdio.h>
+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 <libxml/xmlversion.h>
+
+#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 <string.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_RESOLV_H
+#ifdef HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h>
+#endif
+#include <resolv.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#ifdef SUPPORT_IP6
+#include <resolv.h>
+#endif
+#ifdef HAVE_ZLIB_H
+#include <zlib.h>
+#endif
+
+
+#ifdef VMS
+#include <stropts>
+#define XML_SOCKLEN_T unsigned int
+#define SOCKET int
+#endif
+
+
+#ifdef __MINGW32__
+#define _WINSOCKAPI_
+#include <wsockcompat.h>
+#include <winsock2.h>
+#undef XML_SOCKLEN_T
+#define XML_SOCKLEN_T unsigned int
+#endif
+
+
+#include <libxml/globals.h>
+#include <libxml/xmlerror.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h> /* for xmlStr(n)casecmp() */
+#include <libxml/nanohttp.h>
+#include <libxml/globals.h>
+#include <libxml/uri.h>
+
+/**
+ * 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 <stdio.h>
+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 <libxml/xmlversion.h>
+
+#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 <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/threads.h>
+#include <libxml/globals.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/valid.h>
+#include <libxml/entities.h>
+#include <libxml/xmlerror.h>
+#include <libxml/encoding.h>
+#include <libxml/xmlIO.h>
+#include <libxml/uri.h>
+#ifdef LIBXML_CATALOG_ENABLED
+#include <libxml/catalog.h>
+#endif
+#ifdef LIBXML_SCHEMAS_ENABLED
+#include <libxml/xmlschemastypes.h>
+#include <libxml/relaxng.h>
+#endif
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_ZLIB_H
+#include <zlib.h>
+#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 '<?xml' required\n";
+ break;
+ case XML_ERR_XMLDECL_NOT_FINISHED:
+ errmsg = "parsing XML 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: '</' not found\n";
+ break;
+ case XML_ERR_EQUAL_REQUIRED:
+ errmsg = "expected '='\n";
+ break;
+ case XML_ERR_STRING_NOT_CLOSED:
+ errmsg = "String not closed expecting \" or '\n";
+ break;
+ case XML_ERR_STRING_NOT_STARTED:
+ errmsg = "String not started expecting ' or \"\n";
+ break;
+ case XML_ERR_ENCODING_NAME:
+ errmsg = "Invalid XML encoding name\n";
+ break;
+ case XML_ERR_STANDALONE_VALUE:
+ errmsg = "standalone accepts only 'yes' or 'no'\n";
+ break;
+ case XML_ERR_DOCUMENT_EMPTY:
+ errmsg = "Document is empty\n";
+ break;
+ case XML_ERR_DOCUMENT_END:
+ errmsg = "Extra content at the end of the document\n";
+ break;
+ case XML_ERR_NOT_WELL_BALANCED:
+ errmsg = "chunk is not well balanced\n";
+ break;
+ case XML_ERR_EXTRA_CONTENT:
+ errmsg = "extra content at the end of well balanced chunk\n";
+ break;
+ case XML_ERR_VERSION_MISSING:
+ errmsg = "Malformed declaration expecting version\n";
+ break;
+#if 0
+ case:
+ errmsg = "\n";
+ break;
+#endif
+ default:
+ errmsg = "Unregistered error message\n";
+ }
+ if (ctxt != NULL)
+ ctxt->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; skipl<val; skipl++) { \
+ if (*(ctxt->input->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 "&gt;",
+ * and must, for compatibility, be escaped using "&gt;" 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 ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
+ */
+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<!--%.50s\n", buf);
+ xmlFree(buf);
+ } else {
+ if (input != ctxt->input) {
+ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+ "Comment doesn't start and stop in the same entity\n");
+ }
+ NEXT;
+ if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
+ (!ctxt->disableSAX))
+ ctxt->sax->comment(ctxt->userData, buf);
+ xmlFree(buf);
+ }
+ return;
+not_terminated:
+ xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
+ "Comment not terminated\n", NULL);
+ xmlFree(buf);
+}
+/**
+ * xmlParseComment:
+ * @ctxt: an XML parser context
+ *
+ * Skip an XML (SGML) comment <!-- .... -->
+ * The spec says that "For compatibility, the string "--" (double-hyphen)
+ * must not occur within comments. "
+ *
+ * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
+ */
+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<!--%.50s\n",
+ buf);
+ else
+ xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
+ "Comment not terminated \n", NULL);
+ in++;
+ ctxt->input->col++;
+ }
+ in++;
+ ctxt->input->col++;
+ goto get_more;
+ }
+ } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09));
+ xmlParseCommentComplex(ctxt, buf, len, size);
+ ctxt->instate = state;
+ return;
+}
+
+
+/**
+ * xmlParsePITarget:
+ * @ctxt: an XML parser context
+ *
+ * parse the name of a PI
+ *
+ * [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
+ *
+ * Returns the PITarget name or NULL
+ */
+
+const xmlChar *
+xmlParsePITarget(xmlParserCtxtPtr ctxt) {
+ const xmlChar *name;
+
+ name = xmlParseName(ctxt);
+ if ((name != NULL) &&
+ ((name[0] == 'x') || (name[0] == 'X')) &&
+ ((name[1] == 'm') || (name[1] == 'M')) &&
+ ((name[2] == 'l') || (name[2] == 'L'))) {
+ int i;
+ if ((name[0] == 'x') && (name[1] == 'm') &&
+ (name[2] == 'l') && (name[3] == 0)) {
+ xmlFatalErrMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
+ "XML declaration allowed only at the start of the document\n");
+ return(name);
+ } else if (name[3] == 0) {
+ xmlFatalErr(ctxt, XML_ERR_RESERVED_XML_NAME, NULL);
+ return(name);
+ }
+ for (i = 0;;i++) {
+ if (xmlW3CPIs[i] == NULL) break;
+ if (xmlStrEqual(name, (const xmlChar *)xmlW3CPIs[i]))
+ return(name);
+ }
+ xmlWarningMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
+ "xmlParsePITarget: invalid name prefix 'xml'\n",
+ NULL, NULL);
+ }
+ return(name);
+}
+
+#ifdef LIBXML_CATALOG_ENABLED
+/**
+ * xmlParseCatalogPI:
+ * @ctxt: an XML parser context
+ * @catalog: the PI value string
+ *
+ * parse an XML Catalog Processing Instruction.
+ *
+ * <?oasis-xml-catalog catalog="http://example.com/catalog.xml"?>
+ *
+ * Occurs only if allowed by the user and if happening in the Misc
+ * part of the document before any doctype informations
+ * This will add the given catalog to the parsing context in order
+ * to be used if there is a resolution need further down in the document
+ */
+
+static void
+xmlParseCatalogPI(xmlParserCtxtPtr ctxt, const xmlChar *catalog) {
+ xmlChar *URL = NULL;
+ const xmlChar *tmp, *base;
+ xmlChar marker;
+
+ tmp = catalog;
+ while (IS_BLANK_CH(*tmp)) tmp++;
+ if (xmlStrncmp(tmp, BAD_CAST"catalog", 7))
+ goto error;
+ tmp += 7;
+ while (IS_BLANK_CH(*tmp)) tmp++;
+ if (*tmp != '=') {
+ return;
+ }
+ tmp++;
+ while (IS_BLANK_CH(*tmp)) tmp++;
+ marker = *tmp;
+ if ((marker != '\'') && (marker != '"'))
+ goto error;
+ tmp++;
+ base = tmp;
+ while ((*tmp != 0) && (*tmp != marker)) tmp++;
+ if (*tmp == 0)
+ goto error;
+ URL = xmlStrndup(base, tmp - base);
+ tmp++;
+ while (IS_BLANK_CH(*tmp)) tmp++;
+ if (*tmp != 0)
+ goto error;
+
+ if (URL != NULL) {
+ ctxt->catalogs = xmlCatalogAddLocal(ctxt->catalogs, URL);
+ xmlFree(URL);
+ }
+ return;
+
+error:
+ xmlWarningMsg(ctxt, XML_WAR_CATALOG_PI,
+ "Catalog PI syntax error: %s\n",
+ catalog, NULL);
+ if (URL != NULL)
+ xmlFree(URL);
+}
+#endif
+
+/**
+ * xmlParsePI:
+ * @ctxt: an XML parser context
+ *
+ * parse an XML Processing Instruction.
+ *
+ * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
+ *
+ * The processing is transfered to SAX once parsed.
+ */
+
+void
+xmlParsePI(xmlParserCtxtPtr ctxt) {
+ xmlChar *buf = NULL;
+ int len = 0;
+ int size = XML_PARSER_BUFFER_SIZE;
+ int cur, l;
+ const xmlChar *target;
+ xmlParserInputState state;
+ int count = 0;
+
+ if ((RAW == '<') && (NXT(1) == '?')) {
+ xmlParserInputPtr input = ctxt->input;
+ 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 = xmlParsePITarget(ctxt);
+ if (target != NULL) {
+ if ((RAW == '?') && (NXT(1) == '>')) {
+ if (input != ctxt->input) {
+ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+ "PI declaration doesn't start and stop in the same entity\n");
+ }
+ SKIP(2);
+
+ /*
+ * 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) {
+ xmlErrMemory(ctxt, NULL);
+ ctxt->instate = state;
+ return;
+ }
+ cur = CUR;
+ if (!IS_BLANK(cur)) {
+ xmlFatalErrMsgStr(ctxt, XML_ERR_SPACE_REQUIRED,
+ "ParsePI: PI %s space expected\n", target);
+ }
+ SKIP_BLANKS;
+ cur = CUR_CHAR(l);
+ while (IS_CHAR(cur) && /* checked */
+ ((cur != '?') || (NXT(1) != '>'))) {
+ if (len + 5 >= size) {
+ xmlChar *tmp;
+
+ size *= 2;
+ tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
+ if (tmp == NULL) {
+ xmlErrMemory(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 != '?') {
+ xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
+ "ParsePI: PI %s never end ...\n", target);
+ } else {
+ if (input != ctxt->input) {
+ xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+ "PI declaration doesn't start and stop in the same entity\n");
+ }
+ SKIP(2);
+
+#ifdef LIBXML_CATALOG_ENABLED
+ if (((state == XML_PARSER_MISC) ||
+ (state == XML_PARSER_START)) &&
+ (xmlStrEqual(target, XML_CATALOG_PI))) {
+ xmlCatalogAllow allow = xmlCatalogGetDefaults();
+ if ((allow == XML_CATA_ALLOW_DOCUMENT) ||
+ (allow == XML_CATA_ALLOW_ALL))
+ xmlParseCatalogPI(ctxt, buf);
+ }
+#endif
+
+
+ /*
+ * SAX: PI detected.
+ */
+ if ((ctxt->sax) && (!ctxt->disableSAX) &&
+ (ctxt->sax->processingInstruction != NULL))
+ ctxt->sax->processingInstruction(ctxt->userData,
+ target, buf);
+ }
+ xmlFree(buf);
+ } else {
+ xmlFatalErr(ctxt, XML_ERR_PI_NOT_STARTED, NULL);
+ }
+ ctxt->instate = state;
+ }
+}
+
+/**
+ * xmlParseNotationDecl:
+ * @ctxt: an XML parser context
+ *
+ * parse a notation declaration
+ *
+ * [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID | PublicID) S? '>'
+ *
+ * Hence there is actually 3 choices:
+ * 'PUBLIC' S PubidLiteral
+ * 'PUBLIC' S PubidLiteral S SystemLiteral
+ * and 'SYSTEM' S SystemLiteral
+ *
+ * See the NOTE on xmlParseExternalID().
+ */
+
+void
+xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
+ const xmlChar *name;
+ xmlChar *Pubid;
+ xmlChar *Systemid;
+
+ if (CMP10(CUR_PTR, '<', '!', 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
+ xmlParserInputPtr input = ctxt->input;
+ SHRINK;
+ SKIP(10);
+ if (!IS_BLANK_CH(CUR)) {
+ xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+ "Space required after '<!NOTATION'\n");
+ return;
+ }
+ SKIP_BLANKS;
+
+ name = xmlParseName(ctxt);
+ if (name == NULL) {
+ xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
+ return;
+ }
+ if (!IS_BLANK_CH(CUR)) {
+ xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+ "Space required after the NOTATION name'\n");
+ return;
+ }
+ SKIP_BLANKS;
+
+ /*
+ * Parse the IDs.
+ */
+ Systemid = xmlParseExternalID(ctxt, &Pubid, 0);
+ SKIP_BLANKS;
+
+ if (RAW == '>') {
+ if (input != ctxt->input) {
+ xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+ "Notation declaration doesn't start and stop in the same entity\n");
+ }
+ NEXT;
+ if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
+ (ctxt->sax->notationDecl != NULL))
+ ctxt->sax->notationDecl(ctxt->userData, name, Pubid, Systemid);
+ } else {
+ xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
+ }
+ if (Systemid != NULL) xmlFree(Systemid);
+ if (Pubid != NULL) xmlFree(Pubid);
+ }
+}
+
+/**
+ * xmlParseEntityDecl:
+ * @ctxt: an XML parser context
+ *
+ * parse <!ENTITY declarations
+ *
+ * [70] EntityDecl ::= GEDecl | PEDecl
+ *
+ * [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
+ *
+ * [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
+ *
+ * [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
+ *
+ * [74] PEDef ::= EntityValue | ExternalID
+ *
+ * [76] NDataDecl ::= S 'NDATA' S Name
+ *
+ * [ VC: Notation Declared ]
+ * The Name must match the declared name of a notation.
+ */
+
+void
+xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
+ const xmlChar *name = NULL;
+ xmlChar *value = NULL;
+ xmlChar *URI = NULL, *literal = NULL;
+ const xmlChar *ndata = NULL;
+ int isParameter = 0;
+ xmlChar *orig = NULL;
+ int skipped;
+
+ /* GROW; done in the caller */
+ if (CMP8(CUR_PTR, '<', '!', 'E', 'N', 'T', 'I', 'T', 'Y')) {
+ xmlParserInputPtr input = ctxt->input;
+ SHRINK;
+ SKIP(8);
+ skipped = SKIP_BLANKS;
+ if (skipped == 0) {
+ xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+ "Space required after '<!ENTITY'\n");
+ }
+
+ if (RAW == '%') {
+ NEXT;
+ skipped = SKIP_BLANKS;
+ if (skipped == 0) {
+ xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+ "Space required after '%'\n");
+ }
+ isParameter = 1;
+ }
+
+ name = xmlParseName(ctxt);
+ if (name == NULL) {
+ xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
+ "xmlParseEntityDecl: no name\n");
+ return;
+ }
+ skipped = SKIP_BLANKS;
+ if (skipped == 0) {
+ xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+ "Space required after the entity name\n");
+ }
+
+ ctxt->instate = XML_PARSER_ENTITY_DECL;
+ /*
+ * handle the various case of definitions...
+ */
+ if (isParameter) {
+ if ((RAW == '"') || (RAW == '\'')) {
+ value = xmlParseEntityValue(ctxt, &orig);
+ if (value) {
+ if ((ctxt->sax != NULL) &&
+ (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
+ ctxt->sax->entityDecl(ctxt->userData, name,
+ XML_INTERNAL_PARAMETER_ENTITY,
+ NULL, NULL, value);
+ }
+ } else {
+ URI = xmlParseExternalID(ctxt, &literal, 1);
+ if ((URI == NULL) && (literal == NULL)) {
+ xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
+ }
+ if (URI) {
+ xmlURIPtr uri;
+
+ uri = xmlParseURI((const char *) URI);
+ if (uri == NULL) {
+ xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
+ "Invalid URI: %s\n", URI);
+ /*
+ * This really ought to be a well formedness error
+ * but the XML Core WG decided otherwise c.f. issue
+ * E26 of the XML erratas.
+ */
+ } else {
+ if (uri->fragment != NULL) {
+ /*
+ * Okay this is foolish to block those but not
+ * invalid URIs.
+ */
+ xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
+ } else {
+ if ((ctxt->sax != NULL) &&
+ (!ctxt->disableSAX) &&
+ (ctxt->sax->entityDecl != NULL))
+ ctxt->sax->entityDecl(ctxt->userData, name,
+ XML_EXTERNAL_PARAMETER_ENTITY,
+ literal, URI, NULL);
+ }
+ xmlFreeURI(uri);
+ }
+ }
+ }
+ } else {
+ if ((RAW == '"') || (RAW == '\'')) {
+ value = xmlParseEntityValue(ctxt, &orig);
+ if ((ctxt->sax != NULL) &&
+ (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
+ ctxt->sax->entityDecl(ctxt->userData, name,
+ XML_INTERNAL_GENERAL_ENTITY,
+ NULL, NULL, value);
+ /*
+ * For expat compatibility in SAX mode.
+ */
+ if ((ctxt->myDoc == NULL) ||
+ (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
+ if (ctxt->myDoc == NULL) {
+ ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
+ }
+ if (ctxt->myDoc->intSubset == NULL)
+ ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
+ BAD_CAST "fake", NULL, NULL);
+
+ xmlSAX2EntityDecl(ctxt, name, XML_INTERNAL_GENERAL_ENTITY,
+ NULL, NULL, value);
+ }
+ } else {
+ URI = xmlParseExternalID(ctxt, &literal, 1);
+ if ((URI == NULL) && (literal == NULL)) {
+ xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
+ }
+ if (URI) {
+ xmlURIPtr uri;
+
+ uri = xmlParseURI((const char *)URI);
+ if (uri == NULL) {
+ xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
+ "Invalid URI: %s\n", URI);
+ /*
+ * This really ought to be a well formedness error
+ * but the XML Core WG decided otherwise c.f. issue
+ * E26 of the XML erratas.
+ */
+ } else {
+ if (uri->fragment != NULL) {
+ /*
+ * Okay this is foolish to block those but not
+ * invalid URIs.
+ */
+ xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
+ }
+ xmlFreeURI(uri);
+ }
+ }
+ if ((RAW != '>') && (!IS_BLANK_CH(CUR))) {
+ xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+ "Space required before 'NDATA'\n");
+ }
+ SKIP_BLANKS;
+ if (CMP5(CUR_PTR, 'N', 'D', 'A', 'T', 'A')) {
+ SKIP(5);
+ if (!IS_BLANK_CH(CUR)) {
+ xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+ "Space required after 'NDATA'\n");
+ }
+ SKIP_BLANKS;
+ ndata = xmlParseName(ctxt);
+ if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
+ (ctxt->sax->unparsedEntityDecl != NULL))
+ ctxt->sax->unparsedEntityDecl(ctxt->userData, name,
+ literal, URI, ndata);
+ } else {
+ if ((ctxt->sax != NULL) &&
+ (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
+ ctxt->sax->entityDecl(ctxt->userData, name,
+ XML_EXTERNAL_GENERAL_PARSED_ENTITY,
+ literal, URI, NULL);
+ /*
+ * For expat compatibility in SAX mode.
+ * assuming the entity repalcement was asked for
+ */
+ if ((ctxt->replaceEntities != 0) &&
+ ((ctxt->myDoc == NULL) ||
+ (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE)))) {
+ if (ctxt->myDoc == NULL) {
+ ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
+ }
+
+ if (ctxt->myDoc->intSubset == NULL)
+ ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
+ BAD_CAST "fake", NULL, NULL);
+ xmlSAX2EntityDecl(ctxt, name,
+ XML_EXTERNAL_GENERAL_PARSED_ENTITY,
+ literal, URI, NULL);
+ }
+ }
+ }
+ }
+ SKIP_BLANKS;
+ if (RAW != '>') {
+ xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_NOT_FINISHED,
+ "xmlParseEntityDecl: entity %s not terminated\n", name);
+ } else {
+ if (input != ctxt->input) {
+ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+ "Entity declaration doesn't start and stop in the same entity\n");
+ }
+ NEXT;
+ }
+ if (orig != NULL) {
+ /*
+ * Ugly mechanism to save the raw entity value.
+ */
+ xmlEntityPtr cur = NULL;
+
+ if (isParameter) {
+ if ((ctxt->sax != NULL) &&
+ (ctxt->sax->getParameterEntity != NULL))
+ cur = ctxt->sax->getParameterEntity(ctxt->userData, name);
+ } else {
+ if ((ctxt->sax != NULL) &&
+ (ctxt->sax->getEntity != NULL))
+ cur = ctxt->sax->getEntity(ctxt->userData, name);
+ if ((cur == NULL) && (ctxt->userData==ctxt)) {
+ cur = xmlSAX2GetEntity(ctxt, name);
+ }
+ }
+ if (cur != NULL) {
+ if (cur->orig != NULL)
+ xmlFree(orig);
+ else
+ cur->orig = orig;
+ } else
+ xmlFree(orig);
+ }
+ if (value != NULL) xmlFree(value);
+ if (URI != NULL) xmlFree(URI);
+ if (literal != NULL) xmlFree(literal);
+ }
+}
+
+/**
+ * xmlParseDefaultDecl:
+ * @ctxt: an XML parser context
+ * @value: Receive a possible fixed default value for the attribute
+ *
+ * Parse an attribute default declaration
+ *
+ * [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
+ *
+ * [ VC: Required Attribute ]
+ * if the default declaration is the keyword #REQUIRED, then the
+ * attribute must be specified for all elements of the type in the
+ * attribute-list declaration.
+ *
+ * [ VC: Attribute Default Legal ]
+ * The declared default value must meet the lexical constraints of
+ * the declared attribute type c.f. xmlValidateAttributeDecl()
+ *
+ * [ VC: Fixed Attribute Default ]
+ * if an attribute has a default value declared with the #FIXED
+ * keyword, instances of that attribute must match the default value.
+ *
+ * [ WFC: No < in Attribute Values ]
+ * handled in xmlParseAttValue()
+ *
+ * returns: XML_ATTRIBUTE_NONE, XML_ATTRIBUTE_REQUIRED, XML_ATTRIBUTE_IMPLIED
+ * or XML_ATTRIBUTE_FIXED.
+ */
+
+int
+xmlParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) {
+ int val;
+ xmlChar *ret;
+
+ *value = NULL;
+ if (CMP9(CUR_PTR, '#', 'R', 'E', 'Q', 'U', 'I', 'R', 'E', 'D')) {
+ SKIP(9);
+ return(XML_ATTRIBUTE_REQUIRED);
+ }
+ if (CMP8(CUR_PTR, '#', 'I', 'M', 'P', 'L', 'I', 'E', 'D')) {
+ SKIP(8);
+ return(XML_ATTRIBUTE_IMPLIED);
+ }
+ val = XML_ATTRIBUTE_NONE;
+ if (CMP6(CUR_PTR, '#', 'F', 'I', 'X', 'E', 'D')) {
+ SKIP(6);
+ val = XML_ATTRIBUTE_FIXED;
+ if (!IS_BLANK_CH(CUR)) {
+ xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+ "Space required after '#FIXED'\n");
+ }
+ SKIP_BLANKS;
+ }
+ ret = xmlParseAttValue(ctxt);
+ ctxt->instate = XML_PARSER_DTD;
+ if (ret == NULL) {
+ xmlFatalErrMsg(ctxt, (xmlParserErrors)ctxt->errNo,
+ "Attribute default value declaration error\n");
+ } else
+ *value = ret;
+ return(val);
+}
+
+/**
+ * xmlParseNotationType:
+ * @ctxt: an XML parser context
+ *
+ * parse an Notation attribute type.
+ *
+ * Note: the leading 'NOTATION' S part has already being parsed...
+ *
+ * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
+ *
+ * [ VC: Notation Attributes ]
+ * Values of this type must match one of the notation names included
+ * in the declaration; all notation names in the declaration must be declared.
+ *
+ * Returns: the notation attribute tree built while parsing
+ */
+
+xmlEnumerationPtr
+xmlParseNotationType(xmlParserCtxtPtr ctxt) {
+ const xmlChar *name;
+ xmlEnumerationPtr ret = NULL, last = NULL, cur;
+
+ if (RAW != '(') {
+ xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
+ return(NULL);
+ }
+ SHRINK;
+ do {
+ NEXT;
+ SKIP_BLANKS;
+ name = xmlParseName(ctxt);
+ if (name == NULL) {
+ xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
+ "Name expected in NOTATION declaration\n");
+ return(ret);
+ }
+ cur = xmlCreateEnumeration(name);
+ if (cur == NULL) return(ret);
+ if (last == NULL) ret = last = cur;
+ else {
+ last->next = cur;
+ last = cur;
+ }
+ SKIP_BLANKS;
+ } while (RAW == '|');
+ if (RAW != ')') {
+ xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
+ if ((last != NULL) && (last != ret))
+ xmlFreeEnumeration(last);
+ return(ret);
+ }
+ NEXT;
+ return(ret);
+}
+
+/**
+ * xmlParseEnumerationType:
+ * @ctxt: an XML parser context
+ *
+ * parse an Enumeration attribute type.
+ *
+ * [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
+ *
+ * [ VC: Enumeration ]
+ * Values of this type must match one of the Nmtoken tokens in
+ * the declaration
+ *
+ * Returns: the enumeration attribute tree built while parsing
+ */
+
+xmlEnumerationPtr
+xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
+ xmlChar *name;
+ xmlEnumerationPtr ret = NULL, last = NULL, cur;
+
+ if (RAW != '(') {
+ xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_STARTED, NULL);
+ return(NULL);
+ }
+ SHRINK;
+ do {
+ NEXT;
+ SKIP_BLANKS;
+ name = xmlParseNmtoken(ctxt);
+ if (name == NULL) {
+ xmlFatalErr(ctxt, XML_ERR_NMTOKEN_REQUIRED, NULL);
+ return(ret);
+ }
+ cur = xmlCreateEnumeration(name);
+ xmlFree(name);
+ if (cur == NULL) return(ret);
+ if (last == NULL) ret = last = cur;
+ else {
+ last->next = cur;
+ last = cur;
+ }
+ SKIP_BLANKS;
+ } while (RAW == '|');
+ if (RAW != ')') {
+ xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_FINISHED, NULL);
+ return(ret);
+ }
+ NEXT;
+ return(ret);
+}
+
+/**
+ * xmlParseEnumeratedType:
+ * @ctxt: an XML parser context
+ * @tree: the enumeration tree built while parsing
+ *
+ * parse an Enumerated attribute type.
+ *
+ * [57] EnumeratedType ::= NotationType | Enumeration
+ *
+ * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
+ *
+ *
+ * Returns: XML_ATTRIBUTE_ENUMERATION or XML_ATTRIBUTE_NOTATION
+ */
+
+int
+xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
+ if (CMP8(CUR_PTR, 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
+ SKIP(8);
+ if (!IS_BLANK_CH(CUR)) {
+ xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+ "Space required after 'NOTATION'\n");
+ return(0);
+ }
+ SKIP_BLANKS;
+ *tree = xmlParseNotationType(ctxt);
+ if (*tree == NULL) return(0);
+ return(XML_ATTRIBUTE_NOTATION);
+ }
+ *tree = xmlParseEnumerationType(ctxt);
+ if (*tree == NULL) return(0);
+ return(XML_ATTRIBUTE_ENUMERATION);
+}
+
+/**
+ * xmlParseAttributeType:
+ * @ctxt: an XML parser context
+ * @tree: the enumeration tree built while parsing
+ *
+ * parse the Attribute list def for an element
+ *
+ * [54] AttType ::= StringType | TokenizedType | EnumeratedType
+ *
+ * [55] StringType ::= 'CDATA'
+ *
+ * [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' |
+ * 'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
+ *
+ * Validity constraints for attribute values syntax are checked in
+ * xmlValidateAttributeValue()
+ *
+ * [ VC: ID ]
+ * Values of type ID must match the Name production. A name must not
+ * appear more than once in an XML document as a value of this type;
+ * i.e., ID values must uniquely identify the elements which bear them.
+ *
+ * [ VC: One ID per Element Type ]
+ * No element type may have more than one ID attribute specified.
+ *
+ * [ VC: ID Attribute Default ]
+ * An ID attribute must have a declared default of #IMPLIED or #REQUIRED.
+ *
+ * [ VC: IDREF ]
+ * Values of type IDREF must match the Name production, and values
+ * of type IDREFS must match Names; each IDREF 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 the Name production, values
+ * of type ENTITIES must match Names; each Entity Name must match the
+ * name of an unparsed entity declared in the DTD.
+ *
+ * [ VC: Name Token ]
+ * Values of type NMTOKEN must match the Nmtoken production; values
+ * of type NMTOKENS must match Nmtokens.
+ *
+ * Returns the attribute type
+ */
+int
+xmlParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
+ SHRINK;
+ if (CMP5(CUR_PTR, 'C', 'D', 'A', 'T', 'A')) {
+ SKIP(5);
+ return(XML_ATTRIBUTE_CDATA);
+ } else if (CMP6(CUR_PTR, 'I', 'D', 'R', 'E', 'F', 'S')) {
+ SKIP(6);
+ return(XML_ATTRIBUTE_IDREFS);
+ } else if (CMP5(CUR_PTR, 'I', 'D', 'R', 'E', 'F')) {
+ SKIP(5);
+ return(XML_ATTRIBUTE_IDREF);
+ } else if ((RAW == 'I') && (NXT(1) == 'D')) {
+ SKIP(2);
+ return(XML_ATTRIBUTE_ID);
+ } else if (CMP6(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'Y')) {
+ SKIP(6);
+ return(XML_ATTRIBUTE_ENTITY);
+ } else if (CMP8(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S')) {
+ SKIP(8);
+ return(XML_ATTRIBUTE_ENTITIES);
+ } else if (CMP8(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S')) {
+ SKIP(8);
+ return(XML_ATTRIBUTE_NMTOKENS);
+ } else if (CMP7(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N')) {
+ SKIP(7);
+ return(XML_ATTRIBUTE_NMTOKEN);
+ }
+ return(xmlParseEnumeratedType(ctxt, tree));
+}
+
+/**
+ * xmlParseAttributeListDecl:
+ * @ctxt: an XML parser context
+ *
+ * : parse the Attribute list def for an element
+ *
+ * [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
+ *
+ * [53] AttDef ::= S Name S AttType S DefaultDecl
+ *
+ */
+void
+xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
+ const xmlChar *elemName;
+ const xmlChar *attrName;
+ xmlEnumerationPtr tree;
+
+ if (CMP9(CUR_PTR, '<', '!', 'A', 'T', 'T', 'L', 'I', 'S', 'T')) {
+ xmlParserInputPtr input = ctxt->input;
+
+ SKIP(9);
+ if (!IS_BLANK_CH(CUR)) {
+ xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+ "Space required after '<!ATTLIST'\n");
+ }
+ SKIP_BLANKS;
+ elemName = xmlParseName(ctxt);
+ if (elemName == NULL) {
+ xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
+ "ATTLIST: no name for Element\n");
+ return;
+ }
+ SKIP_BLANKS;
+ GROW;
+ while (RAW != '>') {
+ const xmlChar *check = CUR_PTR;
+ int type;
+ int def;
+ xmlChar *defaultValue = NULL;
+
+ GROW;
+ tree = NULL;
+ attrName = xmlParseName(ctxt);
+ if (attrName == NULL) {
+ xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
+ "ATTLIST: no name for Attribute\n");
+ break;
+ }
+ GROW;
+ if (!IS_BLANK_CH(CUR)) {
+ xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+ "Space required after the attribute name\n");
+ break;
+ }
+ SKIP_BLANKS;
+
+ type = xmlParseAttributeType(ctxt, &tree);
+ if (type <= 0) {
+ break;
+ }
+
+ GROW;
+ if (!IS_BLANK_CH(CUR)) {
+ xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+ "Space required after the attribute type\n");
+ if (tree != NULL)
+ xmlFreeEnumeration(tree);
+ break;
+ }
+ SKIP_BLANKS;
+
+ def = xmlParseDefaultDecl(ctxt, &defaultValue);
+ if (def <= 0) {
+ if (defaultValue != NULL)
+ xmlFree(defaultValue);
+ if (tree != NULL)
+ xmlFreeEnumeration(tree);
+ break;
+ }
+
+ GROW;
+ if (RAW != '>') {
+ if (!IS_BLANK_CH(CUR)) {
+ xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+ "Space required after the attribute default value\n");
+ if (defaultValue != NULL)
+ xmlFree(defaultValue);
+ if (tree != NULL)
+ xmlFreeEnumeration(tree);
+ break;
+ }
+ SKIP_BLANKS;
+ }
+ if (check == CUR_PTR) {
+ xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
+ "in xmlParseAttributeListDecl\n");
+ if (defaultValue != NULL)
+ xmlFree(defaultValue);
+ if (tree != NULL)
+ xmlFreeEnumeration(tree);
+ break;
+ }
+ if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
+ (ctxt->sax->attributeDecl != NULL))
+ ctxt->sax->attributeDecl(ctxt->userData, elemName, attrName,
+ type, def, defaultValue, tree);
+ else if (tree != NULL)
+ xmlFreeEnumeration(tree);
+
+ if ((ctxt->sax2) && (defaultValue != NULL) &&
+ (def != XML_ATTRIBUTE_IMPLIED) &&
+ (def != XML_ATTRIBUTE_REQUIRED)) {
+ xmlAddDefAttrs(ctxt, elemName, attrName, defaultValue);
+ }
+ if ((ctxt->sax2) && (type != XML_ATTRIBUTE_CDATA)) {
+ xmlAddSpecialAttr(ctxt, elemName, attrName, type);
+ }
+ if (defaultValue != NULL)
+ xmlFree(defaultValue);
+ GROW;
+ }
+ if (RAW == '>') {
+ if (input != ctxt->input) {
+ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+ "Attribute list declaration doesn't start and stop in the same entity\n");
+ }
+ NEXT;
+ }
+ }
+}
+
+/**
+ * xmlParseElementMixedContentDecl:
+ * @ctxt: an XML parser context
+ * @inputchk: the input used for the current entity, needed for boundary checks
+ *
+ * parse the declaration for a Mixed Element content
+ * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
+ *
+ * [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' |
+ * '(' S? '#PCDATA' S? ')'
+ *
+ * [ VC: Proper Group/PE Nesting ] applies to [51] too (see [49])
+ *
+ * [ VC: No Duplicate Types ]
+ * The same name must not appear more than once in a single
+ * mixed-content declaration.
+ *
+ * returns: the list of the xmlElementContentPtr describing the element choices
+ */
+xmlElementContentPtr
+xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
+ xmlElementContentPtr ret = NULL, cur = NULL, n;
+ const xmlChar *elem = NULL;
+
+ GROW;
+ if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
+ SKIP(7);
+ SKIP_BLANKS;
+ SHRINK;
+ if (RAW == ')') {
+ if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
+ xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
+"Element content declaration doesn't start and stop in the same entity\n",
+ NULL);
+ }
+ NEXT;
+ ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
+ if (RAW == '*') {
+ ret->ocur = XML_ELEMENT_CONTENT_MULT;
+ NEXT;
+ }
+ return(ret);
+ }
+ if ((RAW == '(') || (RAW == '|')) {
+ ret = cur = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
+ if (ret == NULL) return(NULL);
+ }
+ while (RAW == '|') {
+ NEXT;
+ if (elem == NULL) {
+ ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
+ if (ret == NULL) return(NULL);
+ ret->c1 = cur;
+ if (cur != NULL)
+ cur->parent = ret;
+ cur = ret;
+ } else {
+ n = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
+ if (n == NULL) return(NULL);
+ n->c1 = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
+ if (n->c1 != NULL)
+ n->c1->parent = n;
+ cur->c2 = n;
+ if (n != NULL)
+ n->parent = cur;
+ cur = n;
+ }
+ SKIP_BLANKS;
+ elem = xmlParseName(ctxt);
+ if (elem == NULL) {
+ xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
+ "xmlParseElementMixedContentDecl : Name expected\n");
+ xmlFreeDocElementContent(ctxt->myDoc, cur);
+ return(NULL);
+ }
+ SKIP_BLANKS;
+ GROW;
+ }
+ if ((RAW == ')') && (NXT(1) == '*')) {
+ if (elem != NULL) {
+ cur->c2 = xmlNewDocElementContent(ctxt->myDoc, elem,
+ XML_ELEMENT_CONTENT_ELEMENT);
+ if (cur->c2 != NULL)
+ cur->c2->parent = cur;
+ }
+ ret->ocur = XML_ELEMENT_CONTENT_MULT;
+ if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
+ xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
+"Element content declaration doesn't start and stop in the same entity\n",
+ NULL);
+ }
+ SKIP(2);
+ } else {
+ xmlFreeDocElementContent(ctxt->myDoc, ret);
+ xmlFatalErr(ctxt, XML_ERR_MIXED_NOT_STARTED, NULL);
+ return(NULL);
+ }
+
+ } else {
+ xmlFatalErr(ctxt, XML_ERR_PCDATA_REQUIRED, NULL);
+ }
+ return(ret);
+}
+
+/**
+ * xmlParseElementChildrenContentDecl:
+ * @ctxt: an XML parser context
+ * @inputchk: the input used for the current entity, needed for boundary checks
+ *
+ * parse the declaration for a Mixed Element content
+ * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
+ *
+ *
+ * [47] children ::= (choice | seq) ('?' | '*' | '+')?
+ *
+ * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
+ *
+ * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
+ *
+ * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
+ *
+ * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
+ * TODO Parameter-entity replacement text must be properly nested
+ * with parenthesized groups. That is to say, if either of the
+ * opening or closing parentheses in a choice, seq, or Mixed
+ * construct is contained in the replacement text for a parameter
+ * entity, both must be contained in the same replacement text. For
+ * interoperability, if a parameter-entity reference appears in a
+ * choice, seq, or Mixed construct, its replacement text should not
+ * be empty, and neither the first nor last non-blank character of
+ * the replacement text should be a connector (| or ,).
+ *
+ * Returns the tree of xmlElementContentPtr describing the element
+ * hierarchy.
+ */
+xmlElementContentPtr
+xmlParseElementChildrenContentDecl (xmlParserCtxtPtr ctxt, int inputchk) {
+ xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL;
+ const xmlChar *elem;
+ xmlChar type = 0;
+
+ SKIP_BLANKS;
+ GROW;
+ if (RAW == '(') {
+ int inputid = ctxt->input->id;
+
+ /* Recurse on first child */
+ NEXT;
+ SKIP_BLANKS;
+ cur = ret = xmlParseElementChildrenContentDecl(ctxt, inputid);
+ SKIP_BLANKS;
+ GROW;
+ } else {
+ elem = xmlParseName(ctxt);
+ if (elem == NULL) {
+ xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
+ return(NULL);
+ }
+ cur = ret = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
+ if (cur == NULL) {
+ xmlErrMemory(ctxt, NULL);
+ return(NULL);
+ }
+ GROW;
+ if (RAW == '?') {
+ cur->ocur = XML_ELEMENT_CONTENT_OPT;
+ NEXT;
+ } else if (RAW == '*') {
+ cur->ocur = XML_ELEMENT_CONTENT_MULT;
+ NEXT;
+ } else if (RAW == '+') {
+ cur->ocur = XML_ELEMENT_CONTENT_PLUS;
+ NEXT;
+ } else {
+ cur->ocur = XML_ELEMENT_CONTENT_ONCE;
+ }
+ GROW;
+ }
+ SKIP_BLANKS;
+ SHRINK;
+ while (RAW != ')') {
+ /*
+ * Each loop we parse one separator and one element.
+ */
+ if (RAW == ',') {
+ if (type == 0) type = CUR;
+
+ /*
+ * Detect "Name | Name , Name" error
+ */
+ else if (type != CUR) {
+ xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
+ "xmlParseElementChildrenContentDecl : '%c' expected\n",
+ type);
+ if ((last != NULL) && (last != ret))
+ xmlFreeDocElementContent(ctxt->myDoc, last);
+ if (ret != NULL)
+ xmlFreeDocElementContent(ctxt->myDoc, ret);
+ return(NULL);
+ }
+ NEXT;
+
+ op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_SEQ);
+ if (op == NULL) {
+ if ((last != NULL) && (last != ret))
+ xmlFreeDocElementContent(ctxt->myDoc, last);
+ xmlFreeDocElementContent(ctxt->myDoc, ret);
+ return(NULL);
+ }
+ if (last == NULL) {
+ op->c1 = ret;
+ if (ret != NULL)
+ ret->parent = op;
+ ret = cur = op;
+ } else {
+ cur->c2 = op;
+ if (op != NULL)
+ op->parent = cur;
+ op->c1 = last;
+ if (last != NULL)
+ last->parent = op;
+ cur =op;
+ last = NULL;
+ }
+ } else if (RAW == '|') {
+ if (type == 0) type = CUR;
+
+ /*
+ * Detect "Name , Name | Name" error
+ */
+ else if (type != CUR) {
+ xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
+ "xmlParseElementChildrenContentDecl : '%c' expected\n",
+ type);
+ if ((last != NULL) && (last != ret))
+ xmlFreeDocElementContent(ctxt->myDoc, last);
+ if (ret != NULL)
+ xmlFreeDocElementContent(ctxt->myDoc, ret);
+ return(NULL);
+ }
+ NEXT;
+
+ op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
+ if (op == NULL) {
+ if ((last != NULL) && (last != ret))
+ xmlFreeDocElementContent(ctxt->myDoc, last);
+ if (ret != NULL)
+ xmlFreeDocElementContent(ctxt->myDoc, ret);
+ return(NULL);
+ }
+ if (last == NULL) {
+ op->c1 = ret;
+ if (ret != NULL)
+ ret->parent = op;
+ ret = cur = op;
+ } else {
+ cur->c2 = op;
+ if (op != NULL)
+ op->parent = cur;
+ op->c1 = last;
+ if (last != NULL)
+ last->parent = op;
+ cur =op;
+ last = NULL;
+ }
+ } else {
+ xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED, NULL);
+ if (ret != NULL)
+ xmlFreeDocElementContent(ctxt->myDoc, ret);
+ return(NULL);
+ }
+ GROW;
+ SKIP_BLANKS;
+ GROW;
+ if (RAW == '(') {
+ int inputid = ctxt->input->id;
+ /* Recurse on second child */
+ NEXT;
+ SKIP_BLANKS;
+ last = xmlParseElementChildrenContentDecl(ctxt, inputid);
+ SKIP_BLANKS;
+ } else {
+ elem = xmlParseName(ctxt);
+ if (elem == NULL) {
+ xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
+ if (ret != NULL)
+ xmlFreeDocElementContent(ctxt->myDoc, ret);
+ return(NULL);
+ }
+ last = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
+ if (RAW == '?') {
+ last->ocur = XML_ELEMENT_CONTENT_OPT;
+ NEXT;
+ } else if (RAW == '*') {
+ last->ocur = XML_ELEMENT_CONTENT_MULT;
+ NEXT;
+ } else if (RAW == '+') {
+ last->ocur = XML_ELEMENT_CONTENT_PLUS;
+ NEXT;
+ } else {
+ last->ocur = XML_ELEMENT_CONTENT_ONCE;
+ }
+ }
+ SKIP_BLANKS;
+ GROW;
+ }
+ if ((cur != NULL) && (last != NULL)) {
+ cur->c2 = last;
+ if (last != NULL)
+ last->parent = cur;
+ }
+ if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
+ xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
+"Element content declaration doesn't start and stop in the same entity\n",
+ NULL);
+ }
+ NEXT;
+ if (RAW == '?') {
+ if (ret != NULL) {
+ if ((ret->ocur == XML_ELEMENT_CONTENT_PLUS) ||
+ (ret->ocur == XML_ELEMENT_CONTENT_MULT))
+ ret->ocur = XML_ELEMENT_CONTENT_MULT;
+ else
+ ret->ocur = XML_ELEMENT_CONTENT_OPT;
+ }
+ NEXT;
+ } else if (RAW == '*') {
+ if (ret != NULL) {
+ ret->ocur = XML_ELEMENT_CONTENT_MULT;
+ cur = ret;
+ /*
+ * Some normalization:
+ * (a | b* | c?)* == (a | b | c)*
+ */
+ while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
+ if ((cur->c1 != NULL) &&
+ ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
+ (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT)))
+ cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
+ if ((cur->c2 != NULL) &&
+ ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
+ (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT)))
+ cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
+ cur = cur->c2;
+ }
+ }
+ NEXT;
+ } else if (RAW == '+') {
+ if (ret != NULL) {
+ int found = 0;
+
+ if ((ret->ocur == XML_ELEMENT_CONTENT_OPT) ||
+ (ret->ocur == XML_ELEMENT_CONTENT_MULT))
+ ret->ocur = XML_ELEMENT_CONTENT_MULT;
+ else
+ ret->ocur = XML_ELEMENT_CONTENT_PLUS;
+ /*
+ * Some normalization:
+ * (a | b*)+ == (a | b)*
+ * (a | b?)+ == (a | b)*
+ */
+ while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
+ if ((cur->c1 != NULL) &&
+ ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
+ (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT))) {
+ cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
+ found = 1;
+ }
+ if ((cur->c2 != NULL) &&
+ ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
+ (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT))) {
+ cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
+ found = 1;
+ }
+ cur = cur->c2;
+ }
+ if (found)
+ ret->ocur = XML_ELEMENT_CONTENT_MULT;
+ }
+ NEXT;
+ }
+ return(ret);
+}
+
+/**
+ * xmlParseElementContentDecl:
+ * @ctxt: an XML parser context
+ * @name: the name of the element being defined.
+ * @result: the Element Content pointer will be stored here if any
+ *
+ * parse the declaration for an Element content either Mixed or Children,
+ * the cases EMPTY and ANY are handled directly in xmlParseElementDecl
+ *
+ * [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
+ *
+ * returns: the type of element content XML_ELEMENT_TYPE_xxx
+ */
+
+int
+xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, const xmlChar *name,
+ xmlElementContentPtr *result) {
+
+ xmlElementContentPtr tree = NULL;
+ int inputid = ctxt->input->id;
+ int res;
+
+ *result = NULL;
+
+ if (RAW != '(') {
+ xmlFatalErrMsgStr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
+ "xmlParseElementContentDecl : %s '(' expected\n", name);
+ return(-1);
+ }
+ NEXT;
+ GROW;
+ SKIP_BLANKS;
+ if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
+ tree = xmlParseElementMixedContentDecl(ctxt, inputid);
+ res = XML_ELEMENT_TYPE_MIXED;
+ } else {
+ tree = xmlParseElementChildrenContentDecl(ctxt, inputid);
+ res = XML_ELEMENT_TYPE_ELEMENT;
+ }
+ SKIP_BLANKS;
+ *result = tree;
+ return(res);
+}
+
+/**
+ * xmlParseElementDecl:
+ * @ctxt: an XML parser context
+ *
+ * parse an Element declaration.
+ *
+ * [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
+ *
+ * [ VC: Unique Element Type Declaration ]
+ * No element type may be declared more than once
+ *
+ * Returns the type of the element, or -1 in case of error
+ */
+int
+xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
+ const xmlChar *name;
+ int ret = -1;
+ xmlElementContentPtr content = NULL;
+
+ /* GROW; done in the caller */
+ if (CMP9(CUR_PTR, '<', '!', 'E', 'L', 'E', 'M', 'E', 'N', 'T')) {
+ xmlParserInputPtr input = ctxt->input;
+
+ SKIP(9);
+ if (!IS_BLANK_CH(CUR)) {
+ xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+ "Space required after 'ELEMENT'\n");
+ }
+ SKIP_BLANKS;
+ name = xmlParseName(ctxt);
+ if (name == NULL) {
+ xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
+ "xmlParseElementDecl: no name for Element\n");
+ return(-1);
+ }
+ while ((RAW == 0) && (ctxt->inputNr > 1))
+ xmlPopInput(ctxt);
+ if (!IS_BLANK_CH(CUR)) {
+ xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+ "Space required after the element name\n");
+ }
+ SKIP_BLANKS;
+ if (CMP5(CUR_PTR, 'E', 'M', 'P', 'T', 'Y')) {
+ SKIP(5);
+ /*
+ * Element must always be empty.
+ */
+ ret = XML_ELEMENT_TYPE_EMPTY;
+ } else if ((RAW == 'A') && (NXT(1) == 'N') &&
+ (NXT(2) == 'Y')) {
+ SKIP(3);
+ /*
+ * Element is a generic container.
+ */
+ ret = XML_ELEMENT_TYPE_ANY;
+ } else if (RAW == '(') {
+ ret = xmlParseElementContentDecl(ctxt, name, &content);
+ } else {
+ /*
+ * [ WFC: PEs in Internal Subset ] error handling.
+ */
+ if ((RAW == '%') && (ctxt->external == 0) &&
+ (ctxt->inputNr == 1)) {
+ xmlFatalErrMsg(ctxt, XML_ERR_PEREF_IN_INT_SUBSET,
+ "PEReference: forbidden within markup decl in internal subset\n");
+ } else {
+ xmlFatalErrMsg(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
+ "xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n");
+ }
+ return(-1);
+ }
+
+ SKIP_BLANKS;
+ /*
+ * Pop-up of finished entities.
+ */
+ while ((RAW == 0) && (ctxt->inputNr > 1))
+ xmlPopInput(ctxt);
+ SKIP_BLANKS;
+
+ if (RAW != '>') {
+ xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
+ if (content != NULL) {
+ xmlFreeDocElementContent(ctxt->myDoc, content);
+ }
+ } else {
+ if (input != ctxt->input) {
+ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
+ "Element declaration doesn't start and stop in the same entity\n");
+ }
+
+ NEXT;
+ if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
+ (ctxt->sax->elementDecl != NULL)) {
+ if (content != NULL)
+ content->parent = NULL;
+ ctxt->sax->elementDecl(ctxt->userData, name, ret,
+ content);
+ if ((content != NULL) && (content->parent == NULL)) {
+ /*
+ * this is a trick: if xmlAddElementDecl is called,
+ * instead of copying the full tree it is plugged directly
+ * if called from the parser. Avoid duplicating the
+ * interfaces or change the API/ABI
+ */
+ xmlFreeDocElementContent(ctxt->myDoc, content);
+ }
+ } else if (content != NULL) {
+ xmlFreeDocElementContent(ctxt->myDoc, content);
+ }
+ }
+ }
+ return(ret);
+}
+
+/**
+ * xmlParseConditionalSections
+ * @ctxt: an XML parser context
+ *
+ * [61] conditionalSect ::= includeSect | ignoreSect
+ * [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
+ * [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
+ * [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
+ * [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
+ */
+
+static void
+xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
+ SKIP(3);
+ SKIP_BLANKS;
+ if (CMP7(CUR_PTR, 'I', 'N', 'C', 'L', 'U', 'D', 'E')) {
+ SKIP(7);
+ SKIP_BLANKS;
+ if (RAW != '[') {
+ xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
+ } else {
+ NEXT;
+ }
+ if (xmlParserDebugEntities) {
+ if ((ctxt->input != NULL) && (ctxt->input->filename))
+ xmlGenericError(xmlGenericErrorContext,
+ "%s(%d): ", ctxt->input->filename,
+ ctxt->input->line);
+ xmlGenericError(xmlGenericErrorContext,
+ "Entering INCLUDE Conditional Section\n");
+ }
+
+ while ((RAW != 0) && ((RAW != ']') || (NXT(1) != ']') ||
+ (NXT(2) != '>'))) {
+ const xmlChar *check = CUR_PTR;
+ unsigned int cons = ctxt->input->consumed;
+
+ if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
+ xmlParseConditionalSections(ctxt);
+ } else if (IS_BLANK_CH(CUR)) {
+ NEXT;
+ } else if (RAW == '%') {
+ xmlParsePEReference(ctxt);
+ } else
+ xmlParseMarkupDecl(ctxt);
+
+ /*
+ * Pop-up of finished entities.
+ */
+ while ((RAW == 0) && (ctxt->inputNr > 1))
+ xmlPopInput(ctxt);
+
+ if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
+ xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
+ break;
+ }
+ }
+ if (xmlParserDebugEntities) {
+ if ((ctxt->input != NULL) && (ctxt->input->filename))
+ xmlGenericError(xmlGenericErrorContext,
+ "%s(%d): ", ctxt->input->filename,
+ ctxt->input->line);
+ xmlGenericError(xmlGenericErrorContext,
+ "Leaving INCLUDE Conditional Section\n");
+ }
+
+ } else if (CMP6(CUR_PTR, 'I', 'G', 'N', 'O', 'R', 'E')) {
+ int state;
+ xmlParserInputState instate;
+ int depth = 0;
+
+ SKIP(6);
+ SKIP_BLANKS;
+ if (RAW != '[') {
+ xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
+ } else {
+ NEXT;
+ }
+ if (xmlParserDebugEntities) {
+ if ((ctxt->input != NULL) && (ctxt->input->filename))
+ xmlGenericError(xmlGenericErrorContext,
+ "%s(%d): ", ctxt->input->filename,
+ ctxt->input->line);
+ xmlGenericError(xmlGenericErrorContext,
+ "Entering IGNORE Conditional Section\n");
+ }
+
+ /*
+ * Parse up to the end of the conditional section
+ * But disable SAX event generating DTD building in the meantime
+ */
+ state = ctxt->disableSAX;
+ instate = ctxt->instate;
+ if (ctxt->recovery == 0) ctxt->disableSAX = 1;
+ ctxt->instate = XML_PARSER_IGNORE;
+
+ while ((depth >= 0) && (RAW != 0)) {
+ if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
+ depth++;
+ SKIP(3);
+ continue;
+ }
+ if ((RAW == ']') && (NXT(1) == ']') && (NXT(2) == '>')) {
+ if (--depth >= 0) SKIP(3);
+ continue;
+ }
+ NEXT;
+ continue;
+ }
+
+ ctxt->disableSAX = state;
+ ctxt->instate = instate;
+
+ if (xmlParserDebugEntities) {
+ if ((ctxt->input != NULL) && (ctxt->input->filename))
+ xmlGenericError(xmlGenericErrorContext,
+ "%s(%d): ", ctxt->input->filename,
+ ctxt->input->line);
+ xmlGenericError(xmlGenericErrorContext,
+ "Leaving IGNORE Conditional Section\n");
+ }
+
+ } else {
+ xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD, NULL);
+ }
+
+ if (RAW == 0)
+ SHRINK;
+
+ if (RAW == 0) {
+ xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
+ } else {
+ SKIP(3);
+ }
+}
+
+/**
+ * xmlParseMarkupDecl:
+ * @ctxt: an XML parser context
+ *
+ * parse Markup declarations
+ *
+ * [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl |
+ * NotationDecl | PI | Comment
+ *
+ * [ VC: Proper Declaration/PE Nesting ]
+ * Parameter-entity replacement text must be properly nested with
+ * markup declarations. That is to say, if either the first character
+ * or the last character of a markup declaration (markupdecl above) is
+ * contained in the replacement text for a parameter-entity reference,
+ * both must be contained in the same replacement text.
+ *
+ * [ WFC: PEs in Internal Subset ]
+ * In the internal DTD subset, parameter-entity references can occur
+ * only where markup declarations can occur, not within markup declarations.
+ * (This does not apply to references that occur in external parameter
+ * entities or to the external subset.)
+ */
+void
+xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
+ GROW;
+ if (CUR == '<') {
+ if (NXT(1) == '!') {
+ switch (NXT(2)) {
+ case 'E':
+ if (NXT(3) == 'L')
+ xmlParseElementDecl(ctxt);
+ else if (NXT(3) == 'N')
+ xmlParseEntityDecl(ctxt);
+ break;
+ case 'A':
+ xmlParseAttributeListDecl(ctxt);
+ break;
+ case 'N':
+ xmlParseNotationDecl(ctxt);
+ break;
+ case '-':
+ xmlParseComment(ctxt);
+ break;
+ default:
+ /* there is an error but it will be detected later */
+ break;
+ }
+ } else if (NXT(1) == '?') {
+ xmlParsePI(ctxt);
+ }
+ }
+ /*
+ * This is only for internal subset. On external entities,
+ * the replacement is done before parsing stage
+ */
+ if ((ctxt->external == 0) && (ctxt->inputNr == 1))
+ xmlParsePEReference(ctxt);
+
+ /*
+ * Conditional sections are allowed from entities included
+ * by PE References in the internal subset.
+ */
+ if ((ctxt->external == 0) && (ctxt->inputNr > 1)) {
+ if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
+ xmlParseConditionalSections(ctxt);
+ }
+ }
+
+ ctxt->instate = XML_PARSER_DTD;
+}
+
+/**
+ * xmlParseTextDecl:
+ * @ctxt: an XML parser context
+ *
+ * parse an XML declaration header for external entities
+ *
+ * [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
+ *
+ * Question: Seems that EncodingDecl is mandatory ? Is that a typo ?
+ */
+
+void
+xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
+ xmlChar *version;
+ const xmlChar *encoding;
+
+ /*
+ * We know that '<?xml' is here.
+ */
+ if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
+ SKIP(5);
+ } else {
+ xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_STARTED, NULL);
+ return;
+ }
+
+ if (!IS_BLANK_CH(CUR)) {
+ xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+ "Space needed after '<?xml'\n");
+ }
+ SKIP_BLANKS;
+
+ /*
+ * We may have the VersionInfo here.
+ */
+ version = xmlParseVersionInfo(ctxt);
+ if (version == NULL)
+ version = xmlCharStrdup(XML_DEFAULT_VERSION);
+ else {
+ if (!IS_BLANK_CH(CUR)) {
+ xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+ "Space needed here\n");
+ }
+ }
+ ctxt->input->version = version;
+
+ /*
+ * We must have the encoding declaration
+ */
+ encoding = xmlParseEncodingDecl(ctxt);
+ if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
+ /*
+ * The XML REC instructs us to stop parsing right here
+ */
+ return;
+ }
+ if ((encoding == NULL) && (ctxt->errNo == XML_ERR_OK)) {
+ xmlFatalErrMsg(ctxt, XML_ERR_MISSING_ENCODING,
+ "Missing encoding in text declaration\n");
+ }
+
+ SKIP_BLANKS;
+ if ((RAW == '?') && (NXT(1) == '>')) {
+ SKIP(2);
+ } else if (RAW == '>') {
+ /* Deprecated old WD ... */
+ xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
+ NEXT;
+ } else {
+ xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
+ MOVETO_ENDTAG(CUR_PTR);
+ NEXT;
+ }
+}
+
+/**
+ * xmlParseExternalSubset:
+ * @ctxt: an XML parser context
+ * @ExternalID: the external identifier
+ * @SystemID: the system identifier (or URL)
+ *
+ * parse Markup declarations from an external subset
+ *
+ * [30] extSubset ::= textDecl? extSubsetDecl
+ *
+ * [31] extSubsetDecl ::= (markupdecl | conditionalSect | PEReference | S) *
+ */
+void
+xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
+ const xmlChar *SystemID) {
+ xmlDetectSAX2(ctxt);
+ GROW;
+ if (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) {
+ xmlParseTextDecl(ctxt);
+ if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
+ /*
+ * The XML REC instructs us to stop parsing right here
+ */
+ ctxt->instate = XML_PARSER_EOF;
+ return;
+ }
+ }
+ if (ctxt->myDoc == NULL) {
+ ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
+ }
+ if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL))
+ xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID);
+
+ ctxt->instate = XML_PARSER_DTD;
+ ctxt->external = 1;
+ while (((RAW == '<') && (NXT(1) == '?')) ||
+ ((RAW == '<') && (NXT(1) == '!')) ||
+ (RAW == '%') || IS_BLANK_CH(CUR)) {
+ const xmlChar *check = CUR_PTR;
+ unsigned int cons = ctxt->input->consumed;
+
+ GROW;
+ if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
+ xmlParseConditionalSections(ctxt);
+ } else if (IS_BLANK_CH(CUR)) {
+ NEXT;
+ } else if (RAW == '%') {
+ xmlParsePEReference(ctxt);
+ } else
+ xmlParseMarkupDecl(ctxt);
+
+ /*
+ * Pop-up of finished entities.
+ */
+ while ((RAW == 0) && (ctxt->inputNr > 1))
+ xmlPopInput(ctxt);
+
+ if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
+ xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
+ break;
+ }
+ }
+
+ if (RAW != 0) {
+ xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
+ }
+
+}
+
+/**
+ * xmlParseReference:
+ * @ctxt: an XML parser context
+ *
+ * parse and handle entity references in content, depending on the SAX
+ * interface, this may end-up in a call to character() if this is a
+ * CharRef, a predefined entity, if there is no reference() callback.
+ * or if the parser was asked to switch to that mode.
+ *
+ * [67] Reference ::= EntityRef | CharRef
+ */
+void
+xmlParseReference(xmlParserCtxtPtr ctxt) {
+ xmlEntityPtr ent;
+ xmlChar *val;
+ if (RAW != '&') return;
+
+ if (NXT(1) == '#') {
+ int i = 0;
+ xmlChar out[10];
+ int hex = NXT(2);
+ int value = xmlParseCharRef(ctxt);
+
+ if (ctxt->charset != XML_CHAR_ENCODING_UTF8) {
+ /*
+ * So we are using non-UTF-8 buffers
+ * Check that the char fit on 8bits, if not
+ * generate a CharRef.
+ */
+ if (value <= 0xFF) {
+ out[0] = value;
+ out[1] = 0;
+ if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
+ (!ctxt->disableSAX))
+ ctxt->sax->characters(ctxt->userData, out, 1);
+ } else {
+ if ((hex == 'x') || (hex == 'X'))
+ snprintf((char *)out, sizeof(out), "#x%X", value);
+ else
+ snprintf((char *)out, sizeof(out), "#%d", value);
+ if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
+ (!ctxt->disableSAX))
+ ctxt->sax->reference(ctxt->userData, out);
+ }
+ } else {
+ /*
+ * Just encode the value in UTF-8
+ */
+ COPY_BUF(0 ,out, i, value);
+ out[i] = 0;
+ if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
+ (!ctxt->disableSAX))
+ ctxt->sax->characters(ctxt->userData, out, i);
+ }
+ } else {
+ int was_checked;
+
+ ent = xmlParseEntityRef(ctxt);
+ if (ent == NULL) return;
+ if (!ctxt->wellFormed)
+ return;
+ was_checked = ent->checked;
+ if ((ent->name != NULL) &&
+ (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
+ xmlNodePtr list = NULL;
+ xmlParserErrors ret = XML_ERR_OK;
+
+
+ /*
+ * The first reference to the entity trigger a parsing phase
+ * where the ent->children is filled with the result from
+ * the parsing.
+ */
+ if (ent->checked == 0) {
+ xmlChar *value;
+
+ value = ent->content;
+
+ /*
+ * Check that this entity is well formed
+ */
+ if ((value != NULL) && (value[0] != 0) &&
+ (value[1] == 0) && (value[0] == '<') &&
+ (xmlStrEqual(ent->name, BAD_CAST "lt"))) {
+ /*
+ * DONE: get definite answer on this !!!
+ * Lots of entity decls are used to declare a single
+ * char
+ * <!ENTITY lt "<">
+ * Which seems to be valid since
+ * 2.4: The ampersand character (&) and the left angle
+ * bracket (<) may appear in their literal form only
+ * when used ... They are also legal within the literal
+ * entity value of an internal entity declaration;i
+ * see "4.3.2 Well-Formed Parsed Entities".
+ * IMHO 2.4 and 4.3.2 are directly in contradiction.
+ * Looking at the OASIS test suite and James Clark
+ * tests, this is broken. However the XML REC uses
+ * it. Is the XML REC not well-formed ????
+ * This is a hack to avoid this problem
+ *
+ * ANSWER: since lt gt amp .. are already defined,
+ * this is a redefinition and hence the fact that the
+ * content is not well balanced is not a Wf error, this
+ * is lousy but acceptable.
+ */
+ list = xmlNewDocText(ctxt->myDoc, value);
+ if (list != NULL) {
+ if ((ent->etype == XML_INTERNAL_GENERAL_ENTITY) &&
+ (ent->children == NULL)) {
+ ent->children = list;
+ ent->last = list;
+ ent->owner = 1;
+ list->parent = (xmlNodePtr) ent;
+ } else {
+ xmlFreeNodeList(list);
+ }
+ } else if (list != NULL) {
+ xmlFreeNodeList(list);
+ }
+ } else {
+ /*
+ * 4.3.2: An internal general parsed entity is well-formed
+ * if its replacement text matches the production labeled
+ * content.
+ */
+
+ void *user_data;
+ /*
+ * This is a bit hackish but this seems the best
+ * way to make sure both SAX and DOM entity support
+ * behaves okay.
+ */
+ if (ctxt->userData == ctxt)
+ user_data = NULL;
+ else
+ user_data = ctxt->userData;
+
+ if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
+ ctxt->depth++;
+ ret = xmlParseBalancedChunkMemoryInternal(ctxt,
+ value, user_data, &list);
+ ctxt->depth--;
+ } else if (ent->etype ==
+ XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
+ ctxt->depth++;
+ ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt,
+ ctxt->sax, user_data, ctxt->depth,
+ ent->URI, ent->ExternalID, &list);
+ ctxt->depth--;
+ } else {
+ ret = XML_ERR_ENTITY_PE_INTERNAL;
+ xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
+ "invalid entity type found\n", NULL);
+ }
+ if (ret == XML_ERR_ENTITY_LOOP) {
+ xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
+ return;
+ } else if ((ret == XML_ERR_OK) && (list != NULL)) {
+ if (((ent->etype == XML_INTERNAL_GENERAL_ENTITY) ||
+ (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY))&&
+ (ent->children == NULL)) {
+ ent->children = list;
+ if (ctxt->replaceEntities) {
+ /*
+ * Prune it directly in the generated document
+ * except for single text nodes.
+ */
+ if (((list->type == XML_TEXT_NODE) &&
+ (list->next == NULL)) ||
+ (ctxt->parseMode == XML_PARSE_READER)) {
+ list->parent = (xmlNodePtr) ent;
+ list = NULL;
+ ent->owner = 1;
+ } else {
+ ent->owner = 0;
+ while (list != NULL) {
+ list->parent = (xmlNodePtr) ctxt->node;
+ list->doc = ctxt->myDoc;
+ if (list->next == NULL)
+ ent->last = list;
+ list = list->next;
+ }
+ list = ent->children;
+#ifdef LIBXML_LEGACY_ENABLED
+ if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
+ xmlAddEntityReference(ent, list, NULL);
+#endif /* LIBXML_LEGACY_ENABLED */
+ }
+ } else {
+ ent->owner = 1;
+ while (list != NULL) {
+ list->parent = (xmlNodePtr) ent;
+ if (list->next == NULL)
+ ent->last = list;
+ list = list->next;
+ }
+ }
+ } else {
+ xmlFreeNodeList(list);
+ list = NULL;
+ }
+ } else if ((ret != XML_ERR_OK) &&
+ (ret != XML_WAR_UNDECLARED_ENTITY)) {
+ xmlFatalErr(ctxt, ret, NULL);
+ } else if (list != NULL) {
+ xmlFreeNodeList(list);
+ list = NULL;
+ }
+ }
+ ent->checked = 1;
+ }
+
+ if (ent->children == NULL) {
+ /*
+ * Probably running in SAX mode and the callbacks don't
+ * build the entity content. So unless we already went
+ * though parsing for first checking go though the entity
+ * content to generate callbacks associated to the entity
+ */
+ if (was_checked == 1) {
+ void *user_data;
+ /*
+ * This is a bit hackish but this seems the best
+ * way to make sure both SAX and DOM entity support
+ * behaves okay.
+ */
+ if (ctxt->userData == ctxt)
+ user_data = NULL;
+ else
+ user_data = ctxt->userData;
+
+ if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
+ ctxt->depth++;
+ ret = xmlParseBalancedChunkMemoryInternal(ctxt,
+ ent->content, user_data, NULL);
+ ctxt->depth--;
+ } else if (ent->etype ==
+ XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
+ ctxt->depth++;
+ ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt,
+ ctxt->sax, user_data, ctxt->depth,
+ ent->URI, ent->ExternalID, NULL);
+ ctxt->depth--;
+ } else {
+ ret = XML_ERR_ENTITY_PE_INTERNAL;
+ xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
+ "invalid entity type found\n", NULL);
+ }
+ if (ret == XML_ERR_ENTITY_LOOP) {
+ xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
+ return;
+ }
+ }
+ if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
+ (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
+ /*
+ * Entity reference callback comes second, it's somewhat
+ * superfluous but a compatibility to historical behaviour
+ */
+ ctxt->sax->reference(ctxt->userData, ent->name);
+ }
+ return;
+ }
+ if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
+ (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
+ /*
+ * Create a node.
+ */
+ ctxt->sax->reference(ctxt->userData, ent->name);
+ return;
+ }
+ if ((ctxt->replaceEntities) || (ent->children == NULL)) {
+ /*
+ * There is a problem on the handling of _private for entities
+ * (bug 155816): Should we copy the content of the field from
+ * the entity (possibly overwriting some value set by the user
+ * when a copy is created), should we leave it alone, or should
+ * we try to take care of different situations? The problem
+ * is exacerbated by the usage of this field by the xmlReader.
+ * To fix this bug, we look at _private on the created node
+ * and, if it's NULL, we copy in whatever was in the entity.
+ * If it's not NULL we leave it alone. This is somewhat of a
+ * hack - maybe we should have further tests to determine
+ * what to do.
+ */
+ if ((ctxt->node != NULL) && (ent->children != NULL)) {
+ /*
+ * Seems we are generating the DOM content, do
+ * a simple tree copy for all references except the first
+ * In the first occurrence list contains the replacement.
+ * progressive == 2 means we are operating on the Reader
+ * and since nodes are discarded we must copy all the time.
+ */
+ if (((list == NULL) && (ent->owner == 0)) ||
+ (ctxt->parseMode == XML_PARSE_READER)) {
+ xmlNodePtr nw = NULL, cur, firstChild = NULL;
+
+ /*
+ * when operating on a reader, the entities definitions
+ * are always owning the entities subtree.
+ if (ctxt->parseMode == XML_PARSE_READER)
+ ent->owner = 1;
+ */
+
+ cur = ent->children;
+ while (cur != NULL) {
+ nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
+ if (nw != NULL) {
+ if (nw->_private == NULL)
+ nw->_private = cur->_private;
+ if (firstChild == NULL){
+ firstChild = nw;
+ }
+ nw = xmlAddChild(ctxt->node, nw);
+ }
+ if (cur == ent->last) {
+ /*
+ * needed to detect some strange empty
+ * node cases in the reader tests
+ */
+ if ((ctxt->parseMode == XML_PARSE_READER) &&
+ (nw != NULL) &&
+ (nw->type == XML_ELEMENT_NODE) &&
+ (nw->children == NULL))
+ nw->extra = 1;
+
+ break;
+ }
+ cur = cur->next;
+ }
+#ifdef LIBXML_LEGACY_ENABLED
+ if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
+ xmlAddEntityReference(ent, firstChild, nw);
+#endif /* LIBXML_LEGACY_ENABLED */
+ } else if (list == NULL) {
+ xmlNodePtr nw = NULL, cur, next, last,
+ firstChild = NULL;
+ /*
+ * Copy the entity child list and make it the new
+ * entity child list. The goal is to make sure any
+ * ID or REF referenced will be the one from the
+ * document content and not the entity copy.
+ */
+ cur = ent->children;
+ ent->children = NULL;
+ last = ent->last;
+ ent->last = NULL;
+ while (cur != NULL) {
+ next = cur->next;
+ cur->next = NULL;
+ cur->parent = NULL;
+ nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
+ if (nw != NULL) {
+ if (nw->_private == NULL)
+ nw->_private = cur->_private;
+ if (firstChild == NULL){
+ firstChild = cur;
+ }
+ xmlAddChild((xmlNodePtr) ent, nw);
+ xmlAddChild(ctxt->node, cur);
+ }
+ if (cur == last)
+ break;
+ cur = next;
+ }
+ ent->owner = 1;
+#ifdef LIBXML_LEGACY_ENABLED
+ if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
+ xmlAddEntityReference(ent, firstChild, nw);
+#endif /* LIBXML_LEGACY_ENABLED */
+ } else {
+ const xmlChar *nbktext;
+
+ /*
+ * the name change is to avoid coalescing of the
+ * node with a possible previous text one which
+ * would make ent->children a dangling pointer
+ */
+ nbktext = xmlDictLookup(ctxt->dict, BAD_CAST "nbktext",
+ -1);
+ if (ent->children->type == XML_TEXT_NODE)
+ ent->children->name = nbktext;
+ if ((ent->last != ent->children) &&
+ (ent->last->type == XML_TEXT_NODE))
+ ent->last->name = nbktext;
+ xmlAddChildList(ctxt->node, ent->children);
+ }
+
+ /*
+ * This is to avoid a nasty side effect, see
+ * characters() in SAX.c
+ */
+ ctxt->nodemem = 0;
+ ctxt->nodelen = 0;
+ return;
+ }
+ }
+ } else {
+ val = ent->content;
+ if (val == NULL) return;
+ /*
+ * inline the entity.
+ */
+ if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
+ (!ctxt->disableSAX))
+ ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val));
+ }
+ }
+}
+
+/**
+ * xmlParseEntityRef:
+ * @ctxt: an XML parser context
+ *
+ * parse ENTITY references declarations
+ *
+ * [68] EntityRef ::= '&' Name ';'
+ *
+ * [ 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 Name given in the entity reference
+ * must match that in an entity declaration, except that well-formed
+ * documents need not declare any of the following entities: amp, lt,
+ * gt, apos, quot. The declaration of a parameter entity must precede
+ * any reference to it. Similarly, the declaration of a general entity
+ * must precede any reference to it which appears in a default value in an
+ * attribute-list declaration. Note that if entities are declared in the
+ * external subset or in external parameter entities, a non-validating
+ * processor is not obligated to read and process their declarations;
+ * for such documents, the rule that an entity must be declared is a
+ * well-formedness constraint only if standalone='yes'.
+ *
+ * [ WFC: Parsed Entity ]
+ * An entity reference must not contain the name of an unparsed entity
+ *
+ * Returns the xmlEntityPtr if found, or NULL otherwise.
+ */
+xmlEntityPtr
+xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
+ const xmlChar *name;
+ xmlEntityPtr ent = NULL;
+
+ GROW;
+
+ if (RAW == '&') {
+ NEXT;
+ name = xmlParseName(ctxt);
+ if (name == NULL) {
+ xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
+ "xmlParseEntityRef: no name\n");
+ } else {
+ if (RAW == ';') {
+ NEXT;
+ /*
+ * Ask first SAX for entity resolution, otherwise try the
+ * predefined set.
+ */
+ if (ctxt->sax != NULL) {
+ if (ctxt->sax->getEntity != NULL)
+ ent = ctxt->sax->getEntity(ctxt->userData, name);
+ if ((ctxt->wellFormed == 1 ) && (ent == NULL))
+ ent = xmlGetPredefinedEntity(name);
+ if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
+ (ctxt->userData==ctxt)) {
+ ent = xmlSAX2GetEntity(ctxt, name);
+ }
+ }
+ /*
+ * [ 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
+ * Name given in the entity reference must match that in an
+ * entity declaration, except that well-formed documents
+ * need not declare any of the following entities: amp, lt,
+ * gt, apos, quot.
+ * The declaration of a parameter entity must precede any
+ * reference to it.
+ * Similarly, the declaration of a general entity must
+ * precede any reference to it which appears in a default
+ * value in an attribute-list declaration. Note that if
+ * entities are declared in the external subset or in
+ * external parameter entities, a non-validating processor
+ * is not obligated to read and process their declarations;
+ * for such documents, the rule that an entity must be
+ * declared is a well-formedness constraint only if
+ * standalone='yes'.
+ */
+ if (ent == NULL) {
+ if ((ctxt->standalone == 1) ||
+ ((ctxt->hasExternalSubset == 0) &&
+ (ctxt->hasPErefs == 0))) {
+ xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
+ "Entity '%s' not defined\n", name);
+ } else {
+ xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
+ "Entity '%s' not defined\n", name);
+ if ((ctxt->inSubset == 0) &&
+ (ctxt->sax != NULL) &&
+ (ctxt->sax->reference != NULL)) {
+ ctxt->sax->reference(ctxt->userData, name);
+ }
+ }
+ ctxt->valid = 0;
+ }
+
+ /*
+ * [ WFC: Parsed Entity ]
+ * An entity reference must not contain the name of an
+ * unparsed entity
+ */
+ else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
+ xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
+ "Entity reference to unparsed entity %s\n", name);
+ }
+
+ /*
+ * [ WFC: No External Entity References ]
+ * Attribute values cannot contain direct or indirect
+ * entity references to external entities.
+ */
+ else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
+ (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
+ xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
+ "Attribute references external entity '%s'\n", name);
+ }
+ /*
+ * [ WFC: No < in Attribute Values ]
+ * The replacement text of any entity referred to directly or
+ * indirectly in an attribute value (other than "&lt;") must
+ * not contain a <.
+ */
+ else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
+ (ent != NULL) &&
+ (!xmlStrEqual(ent->name, BAD_CAST "lt")) &&
+ (ent->content != NULL) &&
+ (xmlStrchr(ent->content, '<'))) {
+ xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
+ "'<' in entity '%s' is not allowed in attributes values\n", name);
+ }
+
+ /*
+ * Internal check, no parameter entities here ...
+ */
+ else {
+ switch (ent->etype) {
+ case XML_INTERNAL_PARAMETER_ENTITY:
+ case XML_EXTERNAL_PARAMETER_ENTITY:
+ xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
+ "Attempt to reference the parameter entity '%s'\n",
+ name);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /*
+ * [ WFC: No Recursion ]
+ * A parsed entity must not contain a recursive reference
+ * to itself, either directly or indirectly.
+ * Done somewhere else
+ */
+
+ } else {
+ xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
+ }
+ }
+ }
+ return(ent);
+}
+
+/**
+ * xmlParseStringEntityRef:
+ * @ctxt: an XML parser context
+ * @str: a pointer to an index in the string
+ *
+ * parse ENTITY references declarations, but this version parses it from
+ * a string value.
+ *
+ * [68] EntityRef ::= '&' Name ';'
+ *
+ * [ 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 Name given in the entity reference
+ * must match that in an entity declaration, except that well-formed
+ * documents need not declare any of the following entities: amp, lt,
+ * gt, apos, quot. The declaration of a parameter entity must precede
+ * any reference to it. Similarly, the declaration of a general entity
+ * must precede any reference to it which appears in a default value in an
+ * attribute-list declaration. Note that if entities are declared in the
+ * external subset or in external parameter entities, a non-validating
+ * processor is not obligated to read and process their declarations;
+ * for such documents, the rule that an entity must be declared is a
+ * well-formedness constraint only if standalone='yes'.
+ *
+ * [ WFC: Parsed Entity ]
+ * An entity reference must not contain the name of an unparsed entity
+ *
+ * Returns the xmlEntityPtr if found, or NULL otherwise. The str pointer
+ * is updated to the current location in the string.
+ */
+xmlEntityPtr
+xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
+ xmlChar *name;
+ const xmlChar *ptr;
+ xmlChar cur;
+ xmlEntityPtr ent = NULL;
+
+ if ((str == NULL) || (*str == NULL))
+ return(NULL);
+ ptr = *str;
+ cur = *ptr;
+ if (cur == '&') {
+ ptr++;
+ cur = *ptr;
+ name = xmlParseStringName(ctxt, &ptr);
+ if (name == NULL) {
+ xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
+ "xmlParseStringEntityRef: no name\n");
+ } else {
+ if (*ptr == ';') {
+ ptr++;
+ /*
+ * Ask first SAX for entity resolution, otherwise try the
+ * predefined set.
+ */
+ if (ctxt->sax != NULL) {
+ if (ctxt->sax->getEntity != NULL)
+ ent = ctxt->sax->getEntity(ctxt->userData, name);
+ if (ent == NULL)
+ ent = xmlGetPredefinedEntity(name);
+ if ((ent == NULL) && (ctxt->userData==ctxt)) {
+ ent = xmlSAX2GetEntity(ctxt, name);
+ }
+ }
+ /*
+ * [ 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
+ * Name given in the entity reference must match that in an
+ * entity declaration, except that well-formed documents
+ * need not declare any of the following entities: amp, lt,
+ * gt, apos, quot.
+ * The declaration of a parameter entity must precede any
+ * reference to it.
+ * Similarly, the declaration of a general entity must
+ * precede any reference to it which appears in a default
+ * value in an attribute-list declaration. Note that if
+ * entities are declared in the external subset or in
+ * external parameter entities, a non-validating processor
+ * is not obligated to read and process their declarations;
+ * for such documents, the rule that an entity must be
+ * declared is a well-formedness constraint only if
+ * standalone='yes'.
+ */
+ if (ent == NULL) {
+ if ((ctxt->standalone == 1) ||
+ ((ctxt->hasExternalSubset == 0) &&
+ (ctxt->hasPErefs == 0))) {
+ xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
+ "Entity '%s' not defined\n", name);
+ } else {
+ xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
+ "Entity '%s' not defined\n",
+ name);
+ }
+ /* TODO ? check regressions ctxt->valid = 0; */
+ }
+
+ /*
+ * [ WFC: Parsed Entity ]
+ * An entity reference must not contain the name of an
+ * unparsed entity
+ */
+ else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
+ xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
+ "Entity reference to unparsed entity %s\n", name);
+ }
+
+ /*
+ * [ WFC: No External Entity References ]
+ * Attribute values cannot contain direct or indirect
+ * entity references to external entities.
+ */
+ else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
+ (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
+ xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
+ "Attribute references external entity '%s'\n", name);
+ }
+ /*
+ * [ WFC: No < in Attribute Values ]
+ * The replacement text of any entity referred to directly or
+ * indirectly in an attribute value (other than "&lt;") must
+ * not contain a <.
+ */
+ else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
+ (ent != NULL) &&
+ (!xmlStrEqual(ent->name, BAD_CAST "lt")) &&
+ (ent->content != NULL) &&
+ (xmlStrchr(ent->content, '<'))) {
+ xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
+ "'<' in entity '%s' is not allowed in attributes values\n",
+ name);
+ }
+
+ /*
+ * Internal check, no parameter entities here ...
+ */
+ else {
+ switch (ent->etype) {
+ case XML_INTERNAL_PARAMETER_ENTITY:
+ case XML_EXTERNAL_PARAMETER_ENTITY:
+ xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
+ "Attempt to reference the parameter entity '%s'\n",
+ name);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /*
+ * [ WFC: No Recursion ]
+ * A parsed entity must not contain a recursive reference
+ * to itself, either directly or indirectly.
+ * Done somewhere else
+ */
+
+ } else {
+ xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
+ }
+ xmlFree(name);
+ }
+ }
+ *str = ptr;
+ return(ent);
+}
+
+/**
+ * xmlParsePEReference:
+ * @ctxt: an XML parser context
+ *
+ * parse PEReference declarations
+ * The entity content is handled directly by pushing it's content as
+ * a new input stream.
+ *
+ * [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.
+ */
+void
+xmlParsePEReference(xmlParserCtxtPtr ctxt)
+{
+ const xmlChar *name;
+ xmlEntityPtr entity = NULL;
+ xmlParserInputPtr input;
+
+ if (RAW == '%') {
+ NEXT;
+ name = xmlParseName(ctxt);
+ if (name == NULL) {
+ xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
+ "xmlParsePEReference: no name\n");
+ } 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...
+ */
+ xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
+ "PEReference: %%%s; not found\n",
+ name, NULL);
+ ctxt->valid = 0;
+ }
+ } else {
+ /*
+ * Internal checking in case the entity quest barfed
+ */
+ if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
+ (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
+ xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
+ "Internal: %%%s; is not a parameter entity\n",
+ name, NULL);
+ } else if (ctxt->input->free != deallocblankswrapper) {
+ input =
+ xmlNewBlanksWrapperInputStream(ctxt, entity);
+ xmlPushInput(ctxt, input);
+ } else {
+ /*
+ * TODO !!!
+ * handle the extra spaces added before and after
+ * c.f. http://www.w3.org/TR/REC-xml#as-PE
+ */
+ input = xmlNewEntityInputStream(ctxt, entity);
+ xmlPushInput(ctxt, input);
+ if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
+ (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) &&
+ (IS_BLANK_CH(NXT(5)))) {
+ xmlParseTextDecl(ctxt);
+ if (ctxt->errNo ==
+ XML_ERR_UNSUPPORTED_ENCODING) {
+ /*
+ * The XML REC instructs us to stop parsing
+ * right here
+ */
+ ctxt->instate = XML_PARSER_EOF;
+ return;
+ }
+ }
+ }
+ }
+ ctxt->hasPErefs = 1;
+ } else {
+ xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
+ }
+ }
+ }
+}
+
+/**
+ * xmlParseStringPEReference:
+ * @ctxt: an XML parser context
+ * @str: a pointer to an index in the string
+ *
+ * parse PEReference declarations
+ *
+ * [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.
+ *
+ * Returns the string of the entity content.
+ * str is updated to the current value of the index
+ */
+xmlEntityPtr
+xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
+ const xmlChar *ptr;
+ xmlChar cur;
+ xmlChar *name;
+ xmlEntityPtr entity = NULL;
+
+ if ((str == NULL) || (*str == NULL)) return(NULL);
+ ptr = *str;
+ cur = *ptr;
+ if (cur == '%') {
+ ptr++;
+ cur = *ptr;
+ name = xmlParseStringName(ctxt, &ptr);
+ if (name == NULL) {
+ xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
+ "xmlParseStringPEReference: no name\n");
+ } else {
+ cur = *ptr;
+ if (cur == ';') {
+ ptr++;
+ cur = *ptr;
+ 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...
+ */
+ xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
+ "PEReference: %%%s; not found\n",
+ name, NULL);
+ ctxt->valid = 0;
+ }
+ } else {
+ /*
+ * Internal checking in case the entity quest barfed
+ */
+ if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
+ (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
+ xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
+ "%%%s; is not a parameter entity\n",
+ name, NULL);
+ }
+ }
+ ctxt->hasPErefs = 1;
+ } else {
+ xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
+ }
+ xmlFree(name);
+ }
+ }
+ *str = ptr;
+ return(entity);
+}
+
+/**
+ * xmlParseDocTypeDecl:
+ * @ctxt: an XML parser context
+ *
+ * parse a DOCTYPE declaration
+ *
+ * [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S?
+ * ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
+ *
+ * [ VC: Root Element Type ]
+ * The Name in the document type declaration must match the element
+ * type of the root element.
+ */
+
+void
+xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) {
+ const xmlChar *name = NULL;
+ xmlChar *ExternalID = NULL;
+ xmlChar *URI = NULL;
+
+ /*
+ * We know that '<!DOCTYPE' has been detected.
+ */
+ SKIP(9);
+
+ SKIP_BLANKS;
+
+ /*
+ * Parse the DOCTYPE name.
+ */
+ name = xmlParseName(ctxt);
+ if (name == NULL) {
+ xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
+ "xmlParseDocTypeDecl : no DOCTYPE name !\n");
+ }
+ ctxt->intSubName = name;
+
+ SKIP_BLANKS;
+
+ /*
+ * Check for SystemID and ExternalID
+ */
+ URI = xmlParseExternalID(ctxt, &ExternalID, 1);
+
+ if ((URI != NULL) || (ExternalID != NULL)) {
+ ctxt->hasExternalSubset = 1;
+ }
+ ctxt->extSubURI = URI;
+ ctxt->extSubSystem = ExternalID;
+
+ SKIP_BLANKS;
+
+ /*
+ * Create and update the internal subset.
+ */
+ if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL) &&
+ (!ctxt->disableSAX))
+ ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI);
+
+ /*
+ * Is there any internal subset declarations ?
+ * they are handled separately in xmlParseInternalSubset()
+ */
+ if (RAW == '[')
+ return;
+
+ /*
+ * We should be at the end of the DOCTYPE declaration.
+ */
+ if (RAW != '>') {
+ xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
+ }
+ NEXT;
+}
+
+/**
+ * xmlParseInternalSubset:
+ * @ctxt: an XML parser context
+ *
+ * parse the internal subset declaration
+ *
+ * [28 end] ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
+ */
+
+static void
+xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
+ /*
+ * Is there any DTD definition ?
+ */
+ if (RAW == '[') {
+ ctxt->instate = XML_PARSER_DTD;
+ NEXT;
+ /*
+ * Parse the succession of Markup declarations and
+ * PEReferences.
+ * Subsequence (markupdecl | PEReference | S)*
+ */
+ while (RAW != ']') {
+ const xmlChar *check = CUR_PTR;
+ unsigned int cons = ctxt->input->consumed;
+
+ SKIP_BLANKS;
+ xmlParseMarkupDecl(ctxt);
+ xmlParsePEReference(ctxt);
+
+ /*
+ * Pop-up of finished entities.
+ */
+ while ((RAW == 0) && (ctxt->inputNr > 1))
+ xmlPopInput(ctxt);
+
+ if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
+ xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
+ "xmlParseInternalSubset: error detected in Markup declaration\n");
+ break;
+ }
+ }
+ if (RAW == ']') {
+ NEXT;
+ SKIP_BLANKS;
+ }
+ }
+
+ /*
+ * We should be at the end of the DOCTYPE declaration.
+ */
+ if (RAW != '>') {
+ xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
+ }
+ NEXT;
+}
+
+#ifdef LIBXML_SAX1_ENABLED
+/**
+ * xmlParseAttribute:
+ * @ctxt: an XML parser context
+ * @value: a xmlChar ** used to store the value of the attribute
+ *
+ * parse an attribute
+ *
+ * [41] Attribute ::= Name Eq AttValue
+ *
+ * [ WFC: No External Entity References ]
+ * Attribute values cannot contain direct or indirect entity references
+ * to external entities.
+ *
+ * [ WFC: No < in Attribute Values ]
+ * The replacement text of any entity referred to directly or indirectly in
+ * an attribute value (other than "&lt;") must not contain a <.
+ *
+ * [ VC: Attribute Value Type ]
+ * The attribute must have been declared; the value must be of the type
+ * declared for it.
+ *
+ * [25] Eq ::= S? '=' S?
+ *
+ * With namespace:
+ *
+ * [NS 11] Attribute ::= QName Eq AttValue
+ *
+ * Also the case QName == xmlns:??? is handled independently as a namespace
+ * definition.
+ *
+ * Returns the attribute name, and the value in *value.
+ */
+
+const xmlChar *
+xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) {
+ const xmlChar *name;
+ xmlChar *val;
+
+ *value = NULL;
+ GROW;
+ name = xmlParseName(ctxt);
+ if (name == NULL) {
+ xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
+ "error parsing attribute name\n");
+ return(NULL);
+ }
+
+ /*
+ * read the value
+ */
+ SKIP_BLANKS;
+ if (RAW == '=') {
+ NEXT;
+ SKIP_BLANKS;
+ val = xmlParseAttValue(ctxt);
+ ctxt->instate = XML_PARSER_CONTENT;
+ } else {
+ xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
+ "Specification mandate value for attribute %s\n", name);
+ return(NULL);
+ }
+
+ /*
+ * Check that xml:lang conforms to the specification
+ * No more registered as an error, just generate a warning now
+ * since this was deprecated in XML second edition
+ */
+ if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "xml:lang"))) {
+ if (!xmlCheckLanguageID(val)) {
+ xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
+ "Malformed value for xml:lang : %s\n",
+ val, NULL);
+ }
+ }
+
+ /*
+ * Check that xml:space conforms to the specification
+ */
+ if (xmlStrEqual(name, BAD_CAST "xml:space")) {
+ if (xmlStrEqual(val, BAD_CAST "default"))
+ *(ctxt->space) = 0;
+ else if (xmlStrEqual(val, BAD_CAST "preserve"))
+ *(ctxt->space) = 1;
+ else {
+ xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
+"Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
+ val, NULL);
+ }
+ }
+
+ *value = val;
+ return(name);
+}
+
+/**
+ * xmlParseStartTag:
+ * @ctxt: an XML parser context
+ *
+ * parse a start of tag either for rule element or
+ * EmptyElement. In both case we don't parse the tag closing chars.
+ *
+ * [40] STag ::= '<' Name (S Attribute)* S? '>'
+ *
+ * [ WFC: Unique Att Spec ]
+ * No attribute name may appear more than once in the same start-tag or
+ * empty-element tag.
+ *
+ * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
+ *
+ * [ WFC: Unique Att Spec ]
+ * No attribute name may appear more than once in the same start-tag or
+ * empty-element tag.
+ *
+ * With namespace:
+ *
+ * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
+ *
+ * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
+ *
+ * Returns the element name parsed
+ */
+
+const xmlChar *
+xmlParseStartTag(xmlParserCtxtPtr ctxt) {
+ const xmlChar *name;
+ const xmlChar *attname;
+ xmlChar *attvalue;
+ const xmlChar **atts = ctxt->atts;
+ int nbatts = 0;
+ int maxatts = ctxt->maxatts;
+ int i;
+
+ if (RAW != '<') return(NULL);
+ NEXT1;
+
+ name = xmlParseName(ctxt);
+ if (name == NULL) {
+ xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
+ "xmlParseStartTag: invalid element name\n");
+ return(NULL);
+ }
+
+ /*
+ * Now parse the attributes, it ends up with the ending
+ *
+ * (S Attribute)* S?
+ */
+ SKIP_BLANKS;
+ GROW;
+
+ while ((RAW != '>') &&
+ ((RAW != '/') || (NXT(1) != '>')) &&
+ (IS_BYTE_CHAR(RAW))) {
+ const xmlChar *q = CUR_PTR;
+ unsigned int cons = ctxt->input->consumed;
+
+ attname = xmlParseAttribute(ctxt, &attvalue);
+ if ((attname != NULL) && (attvalue != NULL)) {
+ /*
+ * [ WFC: Unique Att Spec ]
+ * No attribute name may appear more than once in the same
+ * start-tag or empty-element tag.
+ */
+ for (i = 0; i < nbatts;i += 2) {
+ if (xmlStrEqual(atts[i], attname)) {
+ xmlErrAttributeDup(ctxt, NULL, attname);
+ xmlFree(attvalue);
+ goto failed;
+ }
+ }
+ /*
+ * Add the pair to atts
+ */
+ if (atts == NULL) {
+ maxatts = 22; /* allow for 10 attrs by default */
+ atts = (const xmlChar **)
+ xmlMalloc(maxatts * sizeof(xmlChar *));
+ if (atts == NULL) {
+ xmlErrMemory(ctxt, NULL);
+ if (attvalue != NULL)
+ xmlFree(attvalue);
+ goto failed;
+ }
+ ctxt->atts = atts;
+ ctxt->maxatts = maxatts;
+ } else if (nbatts + 4 > maxatts) {
+ const xmlChar **n;
+
+ maxatts *= 2;
+ n = (const xmlChar **) xmlRealloc((void *) atts,
+ maxatts * sizeof(const xmlChar *));
+ if (n == NULL) {
+ xmlErrMemory(ctxt, NULL);
+ if (attvalue != NULL)
+ xmlFree(attvalue);
+ goto failed;
+ }
+ atts = n;
+ ctxt->atts = atts;
+ ctxt->maxatts = maxatts;
+ }
+ atts[nbatts++] = attname;
+ atts[nbatts++] = attvalue;
+ atts[nbatts] = NULL;
+ atts[nbatts + 1] = NULL;
+ } else {
+ if (attvalue != NULL)
+ xmlFree(attvalue);
+ }
+
+failed:
+
+ GROW
+ if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
+ break;
+ if (!IS_BLANK_CH(RAW)) {
+ xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+ "attributes construct error\n");
+ }
+ SKIP_BLANKS;
+ if ((cons == ctxt->input->consumed) && (q == CUR_PTR) &&
+ (attname == NULL) && (attvalue == NULL)) {
+ xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
+ "xmlParseStartTag: problem parsing attributes\n");
+ break;
+ }
+ SHRINK;
+ GROW;
+ }
+
+ /*
+ * SAX: Start of Element !
+ */
+ if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL) &&
+ (!ctxt->disableSAX)) {
+ if (nbatts > 0)
+ ctxt->sax->startElement(ctxt->userData, name, atts);
+ else
+ ctxt->sax->startElement(ctxt->userData, name, NULL);
+ }
+
+ if (atts != NULL) {
+ /* Free only the content strings */
+ for (i = 1;i < nbatts;i+=2)
+ if (atts[i] != NULL)
+ xmlFree((xmlChar *) atts[i]);
+ }
+ return(name);
+}
+
+/**
+ * xmlParseEndTag1:
+ * @ctxt: an XML parser context
+ * @line: line of the start tag
+ * @nsNr: number of namespaces on the start tag
+ *
+ * parse an end of tag
+ *
+ * [42] ETag ::= '</' Name S? '>'
+ *
+ * With namespace
+ *
+ * [NS 9] ETag ::= '</' QName S? '>'
+ */
+
+static void
+xmlParseEndTag1(xmlParserCtxtPtr ctxt, int line) {
+ const xmlChar *name;
+
+ GROW;
+ if ((RAW != '<') || (NXT(1) != '/')) {
+ xmlFatalErrMsg(ctxt, XML_ERR_LTSLASH_REQUIRED,
+ "xmlParseEndTag: '</' not found\n");
+ return;
+ }
+ SKIP(2);
+
+ name = xmlParseNameAndCompare(ctxt,ctxt->name);
+
+ /*
+ * We should definitely be at the ending "S? '>'" part
+ */
+ GROW;
+ SKIP_BLANKS;
+ if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
+ xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
+ } else
+ NEXT1;
+
+ /*
+ * [ WFC: Element Type Match ]
+ * The Name in an element's end-tag must match the element type in the
+ * start-tag.
+ *
+ */
+ if (name != (xmlChar*)1) {
+ if (name == NULL) name = BAD_CAST "unparseable";
+ xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
+ "Opening and ending tag mismatch: %s line %d and %s\n",
+ ctxt->name, line, name);
+ }
+
+ /*
+ * SAX: End of Tag
+ */
+ if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
+ (!ctxt->disableSAX))
+ ctxt->sax->endElement(ctxt->userData, ctxt->name);
+
+ namePop(ctxt);
+ spacePop(ctxt);
+ return;
+}
+
+/**
+ * xmlParseEndTag:
+ * @ctxt: an XML parser context
+ *
+ * parse an end of tag
+ *
+ * [42] ETag ::= '</' Name S? '>'
+ *
+ * With namespace
+ *
+ * [NS 9] ETag ::= '</' QName S? '>'
+ */
+
+void
+xmlParseEndTag(xmlParserCtxtPtr ctxt) {
+ xmlParseEndTag1(ctxt, 0);
+}
+#endif /* LIBXML_SAX1_ENABLED */
+
+/************************************************************************
+ * *
+ * SAX 2 specific operations *
+ * *
+ ************************************************************************/
+
+static const xmlChar *
+xmlParseNCNameComplex(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 != '_'))) {
+ return(NULL);
+ }
+
+ while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
+ ((IS_LETTER(c)) || (IS_DIGIT(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));
+}
+
+/*
+ * xmlGetNamespace:
+ * @ctxt: an XML parser context
+ * @prefix: the prefix to lookup
+ *
+ * Lookup the namespace name for the @prefix (which ca be NULL)
+ * The prefix must come from the @ctxt->dict dictionnary
+ *
+ * Returns the namespace name or NULL if not bound
+ */
+static const xmlChar *
+xmlGetNamespace(xmlParserCtxtPtr ctxt, const xmlChar *prefix) {
+ int i;
+
+ if (prefix == ctxt->str_xml) return(ctxt->str_xml_ns);
+ for (i = ctxt->nsNr - 2;i >= 0;i-=2)
+ if (ctxt->nsTab[i] == prefix) {
+ if ((prefix == NULL) && (*ctxt->nsTab[i + 1] == 0))
+ return(NULL);
+ return(ctxt->nsTab[i + 1]);
+ }
+ return(NULL);
+}
+
+/**
+ * xmlParseNCName:
+ * @ctxt: an XML parser context
+ * @len: lenght of the string parsed
+ *
+ * parse an XML name.
+ *
+ * [4NS] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
+ * CombiningChar | Extender
+ *
+ * [5NS] NCName ::= (Letter | '_') (NCNameChar)*
+ *
+ * Returns the Name parsed or NULL
+ */
+
+static const xmlChar *
+xmlParseNCName(xmlParserCtxtPtr ctxt) {
+ const xmlChar *in;
+ const xmlChar *ret;
+ int count = 0;
+
+ /*
+ * Accelerator for simple ASCII names
+ */
+ in = ctxt->input->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 > 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(xmlParseNCNameComplex(ctxt));
+}
+
+/**
+ * xmlParseQName:
+ * @ctxt: an XML parser context
+ * @prefix: pointer to store the prefix part
+ *
+ * parse an XML Namespace QName
+ *
+ * [6] QName ::= (Prefix ':')? LocalPart
+ * [7] Prefix ::= NCName
+ * [8] LocalPart ::= NCName
+ *
+ * Returns the Name parsed or NULL
+ */
+
+static const xmlChar *
+xmlParseQName(xmlParserCtxtPtr ctxt, const xmlChar **prefix) {
+ const xmlChar *l, *p;
+
+ GROW;
+
+ l = xmlParseNCName(ctxt);
+ if (l == NULL) {
+ if (CUR == ':') {
+ l = xmlParseName(ctxt);
+ if (l != NULL) {
+ xmlNsErr(ctxt, XML_NS_ERR_QNAME,
+ "Failed to parse QName '%s'\n", l, NULL, NULL);
+ *prefix = NULL;
+ return(l);
+ }
+ }
+ return(NULL);
+ }
+ if (CUR == ':') {
+ NEXT;
+ p = l;
+ l = xmlParseNCName(ctxt);
+ if (l == NULL) {
+ xmlChar *tmp;
+
+ xmlNsErr(ctxt, XML_NS_ERR_QNAME,
+ "Failed to parse QName '%s:'\n", p, NULL, NULL);
+ tmp = xmlBuildQName(BAD_CAST "", p, NULL, 0);
+ p = xmlDictLookup(ctxt->dict, tmp, -1);
+ if (tmp != NULL) xmlFree(tmp);
+ *prefix = NULL;
+ return(p);
+ }
+ if (CUR == ':') {
+ xmlChar *tmp;
+
+ xmlNsErr(ctxt, XML_NS_ERR_QNAME,
+ "Failed to parse QName '%s:%s:'\n", p, l, NULL);
+ NEXT;
+ tmp = (xmlChar *) xmlParseName(ctxt);
+ if (tmp != NULL) {
+ tmp = xmlBuildQName(tmp, l, NULL, 0);
+ l = xmlDictLookup(ctxt->dict, tmp, -1);
+ if (tmp != NULL) xmlFree(tmp);
+ *prefix = p;
+ return(l);
+ }
+ tmp = xmlBuildQName(BAD_CAST "", l, NULL, 0);
+ l = xmlDictLookup(ctxt->dict, tmp, -1);
+ if (tmp != NULL) xmlFree(tmp);
+ *prefix = p;
+ return(l);
+ }
+ *prefix = p;
+ } else
+ *prefix = NULL;
+ return(l);
+}
+
+/**
+ * xmlParseQNameAndCompare:
+ * @ctxt: an XML parser context
+ * @name: the localname
+ * @prefix: the prefix, if any.
+ *
+ * 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 *
+xmlParseQNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *name,
+ xmlChar const *prefix) {
+ const xmlChar *cmp = name;
+ const xmlChar *in;
+ const xmlChar *ret;
+ const xmlChar *prefix2;
+
+ if (prefix == NULL) return(xmlParseNameAndCompare(ctxt, name));
+
+ GROW;
+ in = ctxt->input->cur;
+
+ cmp = prefix;
+ while (*in != 0 && *in == *cmp) {
+ ++in;
+ ++cmp;
+ }
+ if ((*cmp == 0) && (*in == ':')) {
+ in++;
+ cmp = name;
+ while (*in != 0 && *in == *cmp) {
+ ++in;
+ ++cmp;
+ }
+ if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
+ /* success */
+ ctxt->input->cur = in;
+ return((const xmlChar*) 1);
+ }
+ }
+ /*
+ * all strings coms from the dictionary, equality can be done directly
+ */
+ ret = xmlParseQName (ctxt, &prefix2);
+ if ((ret == name) && (prefix == prefix2))
+ return((const xmlChar*) 1);
+ return ret;
+}
+
+/**
+ * xmlParseAttValueInternal:
+ * @ctxt: an XML parser context
+ * @len: attribute len result
+ * @alloc: whether the attribute was reallocated as a new string
+ * @normalize: if 1 then further non-CDATA normalization must be done
+ *
+ * parse a value for an attribute.
+ * NOTE: if no normalization is needed, the routine will return pointers
+ * directly from the data buffer.
+ *
+ * 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 if it was copied, this can be detected by val[*len] == 0.
+ */
+
+static xmlChar *
+xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
+ int normalize)
+{
+ xmlChar limit = 0;
+ const xmlChar *in = NULL, *start, *end, *last;
+ xmlChar *ret = NULL;
+
+ GROW;
+ in = (xmlChar *) CUR_PTR;
+ if (*in != '"' && *in != '\'') {
+ xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
+ return (NULL);
+ }
+ ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
+
+ /*
+ * try to handle in this routine the most common case where no
+ * allocation of a new string is required and where content is
+ * pure ASCII.
+ */
+ limit = *in++;
+ end = ctxt->input->end;
+ start = in;
+ if (in >= end) {
+ const xmlChar *oldbase = ctxt->input->base;
+ GROW;
+ if (oldbase != ctxt->input->base) {
+ long delta = ctxt->input->base - oldbase;
+ start = start + delta;
+ in = in + delta;
+ }
+ end = ctxt->input->end;
+ }
+ if (normalize) {
+ /*
+ * Skip any leading spaces
+ */
+ while ((in < end) && (*in != limit) &&
+ ((*in == 0x20) || (*in == 0x9) ||
+ (*in == 0xA) || (*in == 0xD))) {
+ in++;
+ start = in;
+ if (in >= end) {
+ const xmlChar *oldbase = ctxt->input->base;
+ GROW;
+ if (oldbase != ctxt->input->base) {
+ long delta = ctxt->input->base - oldbase;
+ start = start + delta;
+ in = in + delta;
+ }
+ end = ctxt->input->end;
+ }
+ }
+ while ((in < end) && (*in != limit) && (*in >= 0x20) &&
+ (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
+ if ((*in++ == 0x20) && (*in == 0x20)) break;
+ if (in >= end) {
+ const xmlChar *oldbase = ctxt->input->base;
+ GROW;
+ if (oldbase != ctxt->input->base) {
+ long delta = ctxt->input->base - oldbase;
+ start = start + delta;
+ in = in + delta;
+ }
+ end = ctxt->input->end;
+ }
+ }
+ last = in;
+ /*
+ * skip the trailing blanks
+ */
+ while ((last[-1] == 0x20) && (last > start)) last--;
+ while ((in < end) && (*in != limit) &&
+ ((*in == 0x20) || (*in == 0x9) ||
+ (*in == 0xA) || (*in == 0xD))) {
+ in++;
+ if (in >= end) {
+ const xmlChar *oldbase = ctxt->input->base;
+ GROW;
+ if (oldbase != ctxt->input->base) {
+ long delta = ctxt->input->base - oldbase;
+ start = start + delta;
+ in = in + delta;
+ last = last + delta;
+ }
+ end = ctxt->input->end;
+ }
+ }
+ if (*in != limit) goto need_complex;
+ } else {
+ while ((in < end) && (*in != limit) && (*in >= 0x20) &&
+ (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
+ in++;
+ if (in >= end) {
+ const xmlChar *oldbase = ctxt->input->base;
+ GROW;
+ if (oldbase != ctxt->input->base) {
+ long delta = ctxt->input->base - oldbase;
+ start = start + delta;
+ in = in + delta;
+ }
+ end = ctxt->input->end;
+ }
+ }
+ last = in;
+ if (*in != limit) goto need_complex;
+ }
+ in++;
+ if (len != NULL) {
+ *len = last - start;
+ ret = (xmlChar *) start;
+ } else {
+ if (alloc) *alloc = 1;
+ ret = xmlStrndup(start, last - start);
+ }
+ CUR_PTR = in;
+ if (alloc) *alloc = 0;
+ return ret;
+need_complex:
+ if (alloc) *alloc = 1;
+ return xmlParseAttValueComplex(ctxt, len, normalize);
+}
+
+/**
+ * xmlParseAttribute2:
+ * @ctxt: an XML parser context
+ * @pref: the element prefix
+ * @elem: the element name
+ * @prefix: a xmlChar ** used to store the value of the attribute prefix
+ * @value: a xmlChar ** used to store the value of the attribute
+ * @len: an int * to save the length of the attribute
+ * @alloc: an int * to indicate if the attribute was allocated
+ *
+ * parse an attribute in the new SAX2 framework.
+ *
+ * Returns the attribute name, and the value in *value, .
+ */
+
+static const xmlChar *
+xmlParseAttribute2(xmlParserCtxtPtr ctxt,
+ const xmlChar *pref, const xmlChar *elem,
+ const xmlChar **prefix, xmlChar **value,
+ int *len, int *alloc) {
+ const xmlChar *name;
+ xmlChar *val, *internal_val = NULL;
+ int normalize = 0;
+
+ *value = NULL;
+ GROW;
+ name = xmlParseQName(ctxt, prefix);
+ if (name == NULL) {
+ xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
+ "error parsing attribute name\n");
+ return(NULL);
+ }
+
+ /*
+ * get the type if needed
+ */
+ if (ctxt->attsSpecial != NULL) {
+ int type;
+
+ type = (int) (long) xmlHashQLookup2(ctxt->attsSpecial,
+ pref, elem, *prefix, name);
+ if (type != 0) normalize = 1;
+ }
+
+ /*
+ * read the value
+ */
+ SKIP_BLANKS;
+ if (RAW == '=') {
+ NEXT;
+ SKIP_BLANKS;
+ val = xmlParseAttValueInternal(ctxt, len, alloc, normalize);
+ ctxt->instate = XML_PARSER_CONTENT;
+ } else {
+ xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
+ "Specification mandate value for attribute %s\n", name);
+ return(NULL);
+ }
+
+ if (*prefix == ctxt->str_xml) {
+ /*
+ * Check that xml:lang conforms to the specification
+ * No more registered as an error, just generate a warning now
+ * since this was deprecated in XML second edition
+ */
+ if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "lang"))) {
+ internal_val = xmlStrndup(val, *len);
+ if (!xmlCheckLanguageID(internal_val)) {
+ xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
+ "Malformed value for xml:lang : %s\n",
+ internal_val, NULL);
+ }
+ }
+
+ /*
+ * Check that xml:space conforms to the specification
+ */
+ if (xmlStrEqual(name, BAD_CAST "space")) {
+ internal_val = xmlStrndup(val, *len);
+ if (xmlStrEqual(internal_val, BAD_CAST "default"))
+ *(ctxt->space) = 0;
+ else if (xmlStrEqual(internal_val, BAD_CAST "preserve"))
+ *(ctxt->space) = 1;
+ else {
+ xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
+"Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
+ internal_val, NULL);
+ }
+ }
+ if (internal_val) {
+ xmlFree(internal_val);
+ }
+ }
+
+ *value = val;
+ return(name);
+}
+
+/**
+ * xmlParseStartTag2:
+ * @ctxt: an XML parser context
+ *
+ * parse a start of tag either for rule element or
+ * EmptyElement. In both case we don't parse the tag closing chars.
+ * This routine is called when running SAX2 parsing
+ *
+ * [40] STag ::= '<' Name (S Attribute)* S? '>'
+ *
+ * [ WFC: Unique Att Spec ]
+ * No attribute name may appear more than once in the same start-tag or
+ * empty-element tag.
+ *
+ * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
+ *
+ * [ WFC: Unique Att Spec ]
+ * No attribute name may appear more than once in the same start-tag or
+ * empty-element tag.
+ *
+ * With namespace:
+ *
+ * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
+ *
+ * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
+ *
+ * Returns the element name parsed
+ */
+
+static const xmlChar *
+xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
+ const xmlChar **URI, int *tlen) {
+ const xmlChar *localname;
+ const xmlChar *prefix;
+ const xmlChar *attname;
+ const xmlChar *aprefix;
+ const xmlChar *nsname;
+ xmlChar *attvalue;
+ const xmlChar **atts = ctxt->atts;
+ int maxatts = ctxt->maxatts;
+ int nratts, nbatts, nbdef;
+ int i, j, nbNs, attval, oldline, oldcol;
+ const xmlChar *base;
+ unsigned long cur;
+ int nsNr = ctxt->nsNr;
+
+ if (RAW != '<') return(NULL);
+ NEXT1;
+
+ /*
+ * NOTE: it is crucial with the SAX2 API to never call SHRINK beyond that
+ * point since the attribute values may be stored as pointers to
+ * the buffer and calling SHRINK would destroy them !
+ * The Shrinking is only possible once the full set of attribute
+ * callbacks have been done.
+ */
+reparse:
+ SHRINK;
+ base = ctxt->input->base;
+ cur = ctxt->input->cur - ctxt->input->base;
+ oldline = ctxt->input->line;
+ oldcol = ctxt->input->col;
+ nbatts = 0;
+ nratts = 0;
+ nbdef = 0;
+ nbNs = 0;
+ attval = 0;
+ /* Forget any namespaces added during an earlier parse of this element. */
+ ctxt->nsNr = nsNr;
+
+ localname = xmlParseQName(ctxt, &prefix);
+ if (localname == NULL) {
+ xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
+ "StartTag: invalid element name\n");
+ return(NULL);
+ }
+ *tlen = ctxt->input->cur - ctxt->input->base - cur;
+
+ /*
+ * Now parse the attributes, it ends up with the ending
+ *
+ * (S Attribute)* S?
+ */
+ SKIP_BLANKS;
+ GROW;
+ if (ctxt->input->base != base) goto base_changed;
+
+ while ((RAW != '>') &&
+ ((RAW != '/') || (NXT(1) != '>')) &&
+ (IS_BYTE_CHAR(RAW))) {
+ const xmlChar *q = CUR_PTR;
+ unsigned int cons = ctxt->input->consumed;
+ int len = -1, alloc = 0;
+
+ attname = xmlParseAttribute2(ctxt, prefix, localname,
+ &aprefix, &attvalue, &len, &alloc);
+ if (ctxt->input->base != base) {
+ if ((attvalue != NULL) && (alloc != 0))
+ xmlFree(attvalue);
+ attvalue = NULL;
+ goto base_changed;
+ }
+ if ((attname != NULL) && (attvalue != NULL)) {
+ if (len < 0) len = xmlStrlen(attvalue);
+ if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
+ const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
+ xmlURIPtr uri;
+
+ if (*URL != 0) {
+ uri = xmlParseURI((const char *) URL);
+ if (uri == NULL) {
+ xmlWarningMsg(ctxt, XML_WAR_NS_URI,
+ "xmlns: %s not a valid URI\n",
+ URL, NULL);
+ } else {
+ if (uri->scheme == NULL) {
+ xmlWarningMsg(ctxt, XML_WAR_NS_URI_RELATIVE,
+ "xmlns: URI %s is not absolute\n",
+ URL, NULL);
+ }
+ xmlFreeURI(uri);
+ }
+ }
+ /*
+ * check that it's not a defined namespace
+ */
+ for (j = 1;j <= nbNs;j++)
+ if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
+ break;
+ if (j <= nbNs)
+ xmlErrAttributeDup(ctxt, NULL, attname);
+ else
+ if (nsPush(ctxt, NULL, URL) > 0) nbNs++;
+ if (alloc != 0) xmlFree(attvalue);
+ SKIP_BLANKS;
+ continue;
+ }
+ if (aprefix == ctxt->str_xmlns) {
+ const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
+ xmlURIPtr uri;
+
+ if (attname == ctxt->str_xml) {
+ if (URL != ctxt->str_xml_ns) {
+ xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
+ "xml namespace prefix mapped to wrong URI\n",
+ NULL, NULL, NULL);
+ }
+ /*
+ * Do not keep a namespace definition node
+ */
+ if (alloc != 0) xmlFree(attvalue);
+ SKIP_BLANKS;
+ continue;
+ }
+ uri = xmlParseURI((const char *) URL);
+ if (uri == NULL) {
+ xmlWarningMsg(ctxt, XML_WAR_NS_URI,
+ "xmlns:%s: '%s' is not a valid URI\n",
+ attname, URL);
+ } else {
+ if ((ctxt->pedantic) && (uri->scheme == NULL)) {
+ xmlWarningMsg(ctxt, XML_WAR_NS_URI_RELATIVE,
+ "xmlns:%s: URI %s is not absolute\n",
+ attname, URL);
+ }
+ xmlFreeURI(uri);
+ }
+
+ /*
+ * check that it's not a defined namespace
+ */
+ for (j = 1;j <= nbNs;j++)
+ if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
+ break;
+ if (j <= nbNs)
+ xmlErrAttributeDup(ctxt, aprefix, attname);
+ else
+ if (nsPush(ctxt, attname, URL) > 0) nbNs++;
+ if (alloc != 0) xmlFree(attvalue);
+ SKIP_BLANKS;
+ if (ctxt->input->base != base) goto base_changed;
+ continue;
+ }
+
+ /*
+ * Add the pair to atts
+ */
+ if ((atts == NULL) || (nbatts + 5 > maxatts)) {
+ if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
+ if (attvalue[len] == 0)
+ xmlFree(attvalue);
+ goto failed;
+ }
+ maxatts = ctxt->maxatts;
+ atts = ctxt->atts;
+ }
+ ctxt->attallocs[nratts++] = alloc;
+ atts[nbatts++] = attname;
+ atts[nbatts++] = aprefix;
+ atts[nbatts++] = NULL; /* the URI will be fetched later */
+ atts[nbatts++] = attvalue;
+ attvalue += len;
+ atts[nbatts++] = attvalue;
+ /*
+ * tag if some deallocation is needed
+ */
+ if (alloc != 0) attval = 1;
+ } else {
+ if ((attvalue != NULL) && (attvalue[len] == 0))
+ xmlFree(attvalue);
+ }
+
+failed:
+
+ GROW
+ if (ctxt->input->base != base) goto base_changed;
+ if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
+ break;
+ if (!IS_BLANK_CH(RAW)) {
+ xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+ "attributes construct error\n");
+ break;
+ }
+ SKIP_BLANKS;
+ if ((cons == ctxt->input->consumed) && (q == CUR_PTR) &&
+ (attname == NULL) && (attvalue == NULL)) {
+ xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
+ "xmlParseStartTag: problem parsing attributes\n");
+ break;
+ }
+ GROW;
+ if (ctxt->input->base != base) goto base_changed;
+ }
+
+ /*
+ * The attributes defaulting
+ */
+ if (ctxt->attsDefault != NULL) {
+ xmlDefAttrsPtr defaults;
+
+ defaults = xmlHashLookup2(ctxt->attsDefault, localname, prefix);
+ if (defaults != NULL) {
+ for (i = 0;i < defaults->nbAttrs;i++) {
+ attname = defaults->values[4 * i];
+ aprefix = defaults->values[4 * i + 1];
+
+ /*
+ * special work for namespaces defaulted defs
+ */
+ if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
+ /*
+ * check that it's not a defined namespace
+ */
+ for (j = 1;j <= nbNs;j++)
+ if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
+ break;
+ if (j <= nbNs) continue;
+
+ nsname = xmlGetNamespace(ctxt, NULL);
+ if (nsname != defaults->values[4 * i + 2]) {
+ if (nsPush(ctxt, NULL,
+ defaults->values[4 * i + 2]) > 0)
+ nbNs++;
+ }
+ } else if (aprefix == ctxt->str_xmlns) {
+ /*
+ * check that it's not a defined namespace
+ */
+ for (j = 1;j <= nbNs;j++)
+ if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
+ break;
+ if (j <= nbNs) continue;
+
+ nsname = xmlGetNamespace(ctxt, attname);
+ if (nsname != defaults->values[2]) {
+ if (nsPush(ctxt, attname,
+ defaults->values[4 * i + 2]) > 0)
+ nbNs++;
+ }
+ } else {
+ /*
+ * check that it's not a defined attribute
+ */
+ for (j = 0;j < nbatts;j+=5) {
+ if ((attname == atts[j]) && (aprefix == atts[j+1]))
+ break;
+ }
+ if (j < nbatts) continue;
+
+ if ((atts == NULL) || (nbatts + 5 > maxatts)) {
+ if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
+ return(NULL);
+ }
+ maxatts = ctxt->maxatts;
+ atts = ctxt->atts;
+ }
+ atts[nbatts++] = attname;
+ atts[nbatts++] = aprefix;
+ if (aprefix == NULL)
+ atts[nbatts++] = NULL;
+ else
+ atts[nbatts++] = xmlGetNamespace(ctxt, aprefix);
+ atts[nbatts++] = defaults->values[4 * i + 2];
+ atts[nbatts++] = defaults->values[4 * i + 3];
+ nbdef++;
+ }
+ }
+ }
+ }
+
+ /*
+ * The attributes checkings
+ */
+ for (i = 0; i < nbatts;i += 5) {
+ /*
+ * The default namespace does not apply to attribute names.
+ */
+ if (atts[i + 1] != NULL) {
+ nsname = xmlGetNamespace(ctxt, atts[i + 1]);
+ if (nsname == NULL) {
+ xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
+ "Namespace prefix %s for %s on %s is not defined\n",
+ atts[i + 1], atts[i], localname);
+ }
+ atts[i + 2] = nsname;
+ } else
+ nsname = NULL;
+ /*
+ * [ WFC: Unique Att Spec ]
+ * No attribute name may appear more than once in the same
+ * start-tag or empty-element tag.
+ * As extended by the Namespace in XML REC.
+ */
+ for (j = 0; j < i;j += 5) {
+ if (atts[i] == atts[j]) {
+ if (atts[i+1] == atts[j+1]) {
+ xmlErrAttributeDup(ctxt, atts[i+1], atts[i]);
+ break;
+ }
+ if ((nsname != NULL) && (atts[j + 2] == nsname)) {
+ xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED,
+ "Namespaced Attribute %s in '%s' redefined\n",
+ atts[i], nsname, NULL);
+ break;
+ }
+ }
+ }
+ }
+
+ nsname = xmlGetNamespace(ctxt, prefix);
+ if ((prefix != NULL) && (nsname == NULL)) {
+ xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
+ "Namespace prefix %s on %s is not defined\n",
+ prefix, localname, NULL);
+ }
+ *pref = prefix;
+ *URI = nsname;
+
+ /*
+ * SAX: Start of Element !
+ */
+ if ((ctxt->sax != NULL) && (ctxt->sax->startElementNs != NULL) &&
+ (!ctxt->disableSAX)) {
+ if (nbNs > 0)
+ ctxt->sax->startElementNs(ctxt->userData, localname, prefix,
+ nsname, nbNs, &ctxt->nsTab[ctxt->nsNr - 2 * nbNs],
+ nbatts / 5, nbdef, atts);
+ else
+ ctxt->sax->startElementNs(ctxt->userData, localname, prefix,
+ nsname, 0, NULL, nbatts / 5, nbdef, atts);
+ }
+
+ /*
+ * Free up attribute allocated strings if needed
+ */
+ if (attval != 0) {
+ for (i = 3,j = 0; j < nratts;i += 5,j++)
+ if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL))
+ xmlFree((xmlChar *) atts[i]);
+ }
+
+ return(localname);
+
+base_changed:
+ /*
+ * the attribute strings are valid iif the base didn't changed
+ */
+ if (attval != 0) {
+ for (i = 3,j = 0; j < nratts;i += 5,j++)
+ if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL))
+ xmlFree((xmlChar *) atts[i]);
+ }
+ ctxt->input->cur = ctxt->input->base + cur;
+ ctxt->input->line = oldline;
+ ctxt->input->col = oldcol;
+ if (ctxt->wellFormed == 1) {
+ goto reparse;
+ }
+ return(NULL);
+}
+
+/**
+ * xmlParseEndTag2:
+ * @ctxt: an XML parser context
+ * @line: line of the start tag
+ * @nsNr: number of namespaces on the start tag
+ *
+ * parse an end of tag
+ *
+ * [42] ETag ::= '</' Name S? '>'
+ *
+ * With namespace
+ *
+ * [NS 9] ETag ::= '</' QName S? '>'
+ */
+
+static void
+xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlChar *prefix,
+ const xmlChar *URI, int line, int nsNr, int tlen) {
+ const xmlChar *name;
+
+ GROW;
+ if ((RAW != '<') || (NXT(1) != '/')) {
+ xmlFatalErr(ctxt, XML_ERR_LTSLASH_REQUIRED, NULL);
+ return;
+ }
+ SKIP(2);
+
+ if ((tlen > 0) && (xmlStrncmp(ctxt->input->cur, ctxt->name, tlen) == 0)) {
+ if (ctxt->input->cur[tlen] == '>') {
+ ctxt->input->cur += tlen + 1;
+ goto done;
+ }
+ ctxt->input->cur += tlen;
+ name = (xmlChar*)1;
+ } else {
+ if (prefix == NULL)
+ name = xmlParseNameAndCompare(ctxt, ctxt->name);
+ else
+ name = xmlParseQNameAndCompare(ctxt, ctxt->name, prefix);
+ }
+
+ /*
+ * We should definitely be at the ending "S? '>'" part
+ */
+ GROW;
+ SKIP_BLANKS;
+ if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
+ xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
+ } else
+ NEXT1;
+
+ /*
+ * [ WFC: Element Type Match ]
+ * The Name in an element's end-tag must match the element type in the
+ * start-tag.
+ *
+ */
+ if (name != (xmlChar*)1) {
+ if (name == NULL) name = BAD_CAST "unparseable";
+ xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
+ "Opening and ending tag mismatch: %s line %d and %s\n",
+ ctxt->name, line, name);
+ }
+
+ /*
+ * SAX: End of Tag
+ */
+done:
+ if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
+ (!ctxt->disableSAX))
+ ctxt->sax->endElementNs(ctxt->userData, ctxt->name, prefix, URI);
+
+ spacePop(ctxt);
+ if (nsNr != 0)
+ nsPop(ctxt, nsNr);
+ return;
+}
+
+/**
+ * xmlParseCDSect:
+ * @ctxt: an XML parser context
+ *
+ * Parse escaped pure raw content.
+ *
+ * [18] CDSect ::= CDStart CData CDEnd
+ *
+ * [19] CDStart ::= '<![CDATA['
+ *
+ * [20] Data ::= (Char* - (Char* ']]>' Char*))
+ *
+ * [21] CDEnd ::= ']]>'
+ */
+void
+xmlParseCDSect(xmlParserCtxtPtr ctxt) {
+ xmlChar *buf = NULL;
+ int len = 0;
+ int size = XML_PARSER_BUFFER_SIZE;
+ int r, rl;
+ int s, sl;
+ int cur, l;
+ int count = 0;
+
+ /* Check 2.6.0 was NXT(0) not RAW */
+ if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
+ SKIP(9);
+ } else
+ return;
+
+ ctxt->instate = XML_PARSER_CDATA_SECTION;
+ r = CUR_CHAR(rl);
+ if (!IS_CHAR(r)) {
+ xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
+ ctxt->instate = XML_PARSER_CONTENT;
+ return;
+ }
+ NEXTL(rl);
+ s = CUR_CHAR(sl);
+ if (!IS_CHAR(s)) {
+ xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
+ ctxt->instate = XML_PARSER_CONTENT;
+ return;
+ }
+ NEXTL(sl);
+ cur = CUR_CHAR(l);
+ buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
+ if (buf == NULL) {
+ xmlErrMemory(ctxt, NULL);
+ return;
+ }
+ while (IS_CHAR(cur) &&
+ ((r != ']') || (s != ']') || (cur != '>'))) {
+ if (len + 5 >= size) {
+ xmlChar *tmp;
+
+ size *= 2;
+ tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
+ if (tmp == NULL) {
+ xmlFree(buf);
+ xmlErrMemory(ctxt, NULL);
+ return;
+ }
+ buf = tmp;
+ }
+ COPY_BUF(rl,buf,len,r);
+ r = s;
+ rl = sl;
+ s = cur;
+ sl = l;
+ count++;
+ if (count > 50) {
+ GROW;
+ count = 0;
+ }
+ NEXTL(l);
+ cur = CUR_CHAR(l);
+ }
+ buf[len] = 0;
+ ctxt->instate = XML_PARSER_CONTENT;
+ if (cur != '>') {
+ xmlFatalErrMsgStr(ctxt, XML_ERR_CDATA_NOT_FINISHED,
+ "CData section not finished\n%.50s\n", buf);
+ xmlFree(buf);
+ return;
+ }
+ NEXTL(l);
+
+ /*
+ * OK the buffer is to be consumed as cdata.
+ */
+ if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
+ if (ctxt->sax->cdataBlock != NULL)
+ ctxt->sax->cdataBlock(ctxt->userData, buf, len);
+ else if (ctxt->sax->characters != NULL)
+ ctxt->sax->characters(ctxt->userData, buf, len);
+ }
+ xmlFree(buf);
+}
+
+/**
+ * xmlParseContent:
+ * @ctxt: an XML parser context
+ *
+ * Parse a content:
+ *
+ * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
+ */
+
+void
+xmlParseContent(xmlParserCtxtPtr ctxt) {
+ GROW;
+ while ((RAW != 0) &&
+ ((RAW != '<') || (NXT(1) != '/')) &&
+ (ctxt->instate != XML_PARSER_EOF)) {
+ const xmlChar *test = CUR_PTR;
+ unsigned int cons = ctxt->input->consumed;
+ const xmlChar *cur = ctxt->input->cur;
+
+ /*
+ * First case : a Processing Instruction.
+ */
+ if ((*cur == '<') && (cur[1] == '?')) {
+ xmlParsePI(ctxt);
+ }
+
+ /*
+ * Second case : a CDSection
+ */
+ /* 2.6.0 test was *cur not RAW */
+ else if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
+ xmlParseCDSect(ctxt);
+ }
+
+ /*
+ * Third case : a comment
+ */
+ else if ((*cur == '<') && (NXT(1) == '!') &&
+ (NXT(2) == '-') && (NXT(3) == '-')) {
+ xmlParseComment(ctxt);
+ ctxt->instate = XML_PARSER_CONTENT;
+ }
+
+ /*
+ * Fourth case : a sub-element.
+ */
+ else if (*cur == '<') {
+ xmlParseElement(ctxt);
+ }
+
+ /*
+ * Fifth case : a reference. If if has not been resolved,
+ * parsing returns it's Name, create the node
+ */
+
+ else if (*cur == '&') {
+ xmlParseReference(ctxt);
+ }
+
+ /*
+ * Last case, text. Note that References are handled directly.
+ */
+ else {
+ xmlParseCharData(ctxt, 0);
+ }
+
+ GROW;
+ /*
+ * Pop-up of finished entities.
+ */
+ while ((RAW == 0) && (ctxt->inputNr > 1))
+ xmlPopInput(ctxt);
+ SHRINK;
+
+ if ((cons == ctxt->input->consumed) && (test == CUR_PTR)) {
+ xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
+ "detected an error in element content\n");
+ ctxt->instate = XML_PARSER_EOF;
+ break;
+ }
+ }
+}
+
+/**
+ * xmlParseElement:
+ * @ctxt: an XML parser context
+ *
+ * parse an XML element, this is highly recursive
+ *
+ * [39] element ::= EmptyElemTag | STag content ETag
+ *
+ * [ WFC: Element Type Match ]
+ * The Name in an element's end-tag must match the element type in the
+ * start-tag.
+ *
+ */
+
+void
+xmlParseElement(xmlParserCtxtPtr ctxt) {
+ const xmlChar *name;
+ const xmlChar *prefix;
+ const xmlChar *URI;
+ xmlParserNodeInfo node_info;
+ int line, tlen;
+ xmlNodePtr ret;
+ int nsNr = ctxt->nsNr;
+
+ if ((unsigned int) ctxt->nameNr > xmlParserMaxDepth) {
+ xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
+ "Excessive depth in document: change xmlParserMaxDepth = %d\n",
+ xmlParserMaxDepth);
+ ctxt->instate = XML_PARSER_EOF;
+ return;
+ }
+
+ /* Capture start position */
+ if (ctxt->record_info) {
+ node_info.begin_pos = ctxt->input->consumed +
+ (CUR_PTR - ctxt->input->base);
+ node_info.begin_line = ctxt->input->line;
+ }
+
+ if (ctxt->spaceNr == 0)
+ spacePush(ctxt, -1);
+ else if (*ctxt->space == -2)
+ spacePush(ctxt, -1);
+ else
+ spacePush(ctxt, *ctxt->space);
+
+ line = ctxt->input->line;
+#ifdef LIBXML_SAX1_ENABLED
+ if (ctxt->sax2)
+#endif /* LIBXML_SAX1_ENABLED */
+ name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen);
+#ifdef LIBXML_SAX1_ENABLED
+ else
+ name = xmlParseStartTag(ctxt);
+#endif /* LIBXML_SAX1_ENABLED */
+ if (name == NULL) {
+ spacePop(ctxt);
+ return;
+ }
+ namePush(ctxt, name);
+ ret = ctxt->node;
+
+#ifdef LIBXML_VALID_ENABLED
+ /*
+ * [ VC: Root Element Type ]
+ * The Name in the document type declaration must match the element
+ * type of the root element.
+ */
+ if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
+ ctxt->node && (ctxt->node == ctxt->myDoc->children))
+ ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
+#endif /* LIBXML_VALID_ENABLED */
+
+ /*
+ * Check for an Empty Element.
+ */
+ if ((RAW == '/') && (NXT(1) == '>')) {
+ SKIP(2);
+ if (ctxt->sax2) {
+ if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
+ (!ctxt->disableSAX))
+ ctxt->sax->endElementNs(ctxt->userData, name, prefix, URI);
+#ifdef LIBXML_SAX1_ENABLED
+ } else {
+ if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
+ (!ctxt->disableSAX))
+ ctxt->sax->endElement(ctxt->userData, name);
+#endif /* LIBXML_SAX1_ENABLED */
+ }
+ namePop(ctxt);
+ spacePop(ctxt);
+ if (nsNr != ctxt->nsNr)
+ nsPop(ctxt, ctxt->nsNr - nsNr);
+ if ( ret != NULL && ctxt->record_info ) {
+ node_info.end_pos = ctxt->input->consumed +
+ (CUR_PTR - ctxt->input->base);
+ node_info.end_line = ctxt->input->line;
+ node_info.node = ret;
+ xmlParserAddNodeInfo(ctxt, &node_info);
+ }
+ return;
+ }
+ if (RAW == '>') {
+ NEXT1;
+ } else {
+ xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_GT_REQUIRED,
+ "Couldn't find end of Start Tag %s line %d\n",
+ name, line, NULL);
+
+ /*
+ * end of parsing of this node.
+ */
+ nodePop(ctxt);
+ namePop(ctxt);
+ spacePop(ctxt);
+ if (nsNr != ctxt->nsNr)
+ nsPop(ctxt, ctxt->nsNr - nsNr);
+
+ /*
+ * Capture end position and add node
+ */
+ if ( ret != NULL && ctxt->record_info ) {
+ node_info.end_pos = ctxt->input->consumed +
+ (CUR_PTR - ctxt->input->base);
+ node_info.end_line = ctxt->input->line;
+ node_info.node = ret;
+ xmlParserAddNodeInfo(ctxt, &node_info);
+ }
+ return;
+ }
+
+ /*
+ * Parse the content of the element:
+ */
+ xmlParseContent(ctxt);
+ if (!IS_BYTE_CHAR(RAW)) {
+ xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
+ "Premature end of data in tag %s line %d\n",
+ name, line, NULL);
+
+ /*
+ * end of parsing of this node.
+ */
+ nodePop(ctxt);
+ namePop(ctxt);
+ spacePop(ctxt);
+ if (nsNr != ctxt->nsNr)
+ nsPop(ctxt, ctxt->nsNr - nsNr);
+ return;
+ }
+
+ /*
+ * parse the end of tag: '</' should be here.
+ */
+ if (ctxt->sax2) {
+ xmlParseEndTag2(ctxt, prefix, URI, line, ctxt->nsNr - nsNr, tlen);
+ namePop(ctxt);
+ }
+#ifdef LIBXML_SAX1_ENABLED
+ else
+ xmlParseEndTag1(ctxt, line);
+#endif /* LIBXML_SAX1_ENABLED */
+
+ /*
+ * Capture end position and add node
+ */
+ if ( ret != NULL && ctxt->record_info ) {
+ node_info.end_pos = ctxt->input->consumed +
+ (CUR_PTR - ctxt->input->base);
+ node_info.end_line = ctxt->input->line;
+ node_info.node = ret;
+ xmlParserAddNodeInfo(ctxt, &node_info);
+ }
+}
+
+/**
+ * xmlParseVersionNum:
+ * @ctxt: an XML parser context
+ *
+ * parse the XML version value.
+ *
+ * [26] VersionNum ::= ([a-zA-Z0-9_.:] | '-')+
+ *
+ * Returns the string giving the XML version number, or NULL
+ */
+xmlChar *
+xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
+ xmlChar *buf = NULL;
+ int len = 0;
+ int size = 10;
+ xmlChar cur;
+
+ buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
+ if (buf == NULL) {
+ xmlErrMemory(ctxt, NULL);
+ return(NULL);
+ }
+ cur = CUR;
+ while (((cur >= 'a') && (cur <= 'z')) ||
+ ((cur >= 'A') && (cur <= 'Z')) ||
+ ((cur >= '0') && (cur <= '9')) ||
+ (cur == '_') || (cur == '.') ||
+ (cur == ':') || (cur == '-')) {
+ if (len + 1 >= size) {
+ xmlChar *tmp;
+
+ size *= 2;
+ tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
+ if (tmp == NULL) {
+ xmlErrMemory(ctxt, NULL);
+ return(NULL);
+ }
+ buf = tmp;
+ }
+ buf[len++] = cur;
+ NEXT;
+ cur=CUR;
+ }
+ buf[len] = 0;
+ return(buf);
+}
+
+/**
+ * xmlParseVersionInfo:
+ * @ctxt: an XML parser context
+ *
+ * parse the XML version.
+ *
+ * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
+ *
+ * [25] Eq ::= S? '=' S?
+ *
+ * Returns the version string, e.g. "1.0"
+ */
+
+xmlChar *
+xmlParseVersionInfo(xmlParserCtxtPtr ctxt) {
+ xmlChar *version = NULL;
+
+ if (CMP7(CUR_PTR, 'v', 'e', 'r', 's', 'i', 'o', 'n')) {
+ SKIP(7);
+ SKIP_BLANKS;
+ if (RAW != '=') {
+ xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
+ return(NULL);
+ }
+ NEXT;
+ SKIP_BLANKS;
+ if (RAW == '"') {
+ NEXT;
+ version = xmlParseVersionNum(ctxt);
+ if (RAW != '"') {
+ xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
+ } else
+ NEXT;
+ } else if (RAW == '\''){
+ NEXT;
+ version = xmlParseVersionNum(ctxt);
+ if (RAW != '\'') {
+ xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
+ } else
+ NEXT;
+ } else {
+ xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
+ }
+ }
+ return(version);
+}
+
+/**
+ * xmlParseEncName:
+ * @ctxt: an XML parser context
+ *
+ * parse the XML encoding name
+ *
+ * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
+ *
+ * Returns the encoding name value or NULL
+ */
+xmlChar *
+xmlParseEncName(xmlParserCtxtPtr ctxt) {
+ xmlChar *buf = NULL;
+ int len = 0;
+ int size = 10;
+ xmlChar cur;
+
+ cur = CUR;
+ if (((cur >= 'a') && (cur <= 'z')) ||
+ ((cur >= 'A') && (cur <= 'Z'))) {
+ buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
+ if (buf == NULL) {
+ xmlErrMemory(ctxt, NULL);
+ return(NULL);
+ }
+
+ buf[len++] = cur;
+ NEXT;
+ cur = CUR;
+ while (((cur >= 'a') && (cur <= 'z')) ||
+ ((cur >= 'A') && (cur <= 'Z')) ||
+ ((cur >= '0') && (cur <= '9')) ||
+ (cur == '.') || (cur == '_') ||
+ (cur == '-')) {
+ 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;
+ NEXT;
+ cur = CUR;
+ if (cur == 0) {
+ SHRINK;
+ GROW;
+ cur = CUR;
+ }
+ }
+ buf[len] = 0;
+ } else {
+ xmlFatalErr(ctxt, XML_ERR_ENCODING_NAME, NULL);
+ }
+ return(buf);
+}
+
+/**
+ * xmlParseEncodingDecl:
+ * @ctxt: an XML parser context
+ *
+ * parse the XML encoding declaration
+ *
+ * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'")
+ *
+ * this setups the conversion filters.
+ *
+ * Returns the encoding value or NULL
+ */
+
+const xmlChar *
+xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
+ xmlChar *encoding = NULL;
+
+ SKIP_BLANKS;
+ if (CMP8(CUR_PTR, 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g')) {
+ SKIP(8);
+ SKIP_BLANKS;
+ if (RAW != '=') {
+ xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
+ return(NULL);
+ }
+ NEXT;
+ SKIP_BLANKS;
+ if (RAW == '"') {
+ NEXT;
+ encoding = xmlParseEncName(ctxt);
+ if (RAW != '"') {
+ xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
+ } else
+ NEXT;
+ } else if (RAW == '\''){
+ NEXT;
+ encoding = xmlParseEncName(ctxt);
+ if (RAW != '\'') {
+ xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
+ } else
+ NEXT;
+ } else {
+ xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
+ }
+ /*
+ * UTF-16 encoding stwich has already taken place at this stage,
+ * more over the little-endian/big-endian selection is already done
+ */
+ if ((encoding != NULL) &&
+ ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-16")) ||
+ (!xmlStrcasecmp(encoding, BAD_CAST "UTF16")))) {
+ if (ctxt->encoding != NULL)
+ xmlFree((xmlChar *) ctxt->encoding);
+ ctxt->encoding = encoding;
+ }
+ /*
+ * UTF-8 encoding is handled natively
+ */
+ else if ((encoding != NULL) &&
+ ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-8")) ||
+ (!xmlStrcasecmp(encoding, BAD_CAST "UTF8")))) {
+ if (ctxt->encoding != NULL)
+ xmlFree((xmlChar *) ctxt->encoding);
+ ctxt->encoding = encoding;
+ }
+ else if (encoding != NULL) {
+ xmlCharEncodingHandlerPtr handler;
+
+ if (ctxt->input->encoding != NULL)
+ xmlFree((xmlChar *) ctxt->input->encoding);
+ ctxt->input->encoding = encoding;
+
+ handler = xmlFindCharEncodingHandler((const char *) encoding);
+ if (handler != NULL) {
+ xmlSwitchToEncoding(ctxt, handler);
+ } else {
+ xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
+ "Unsupported encoding %s\n", encoding);
+ return(NULL);
+ }
+ }
+ }
+ return(encoding);
+}
+
+/**
+ * xmlParseSDDecl:
+ * @ctxt: an XML parser context
+ *
+ * parse the XML standalone declaration
+ *
+ * [32] SDDecl ::= S 'standalone' Eq
+ * (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no')'"'))
+ *
+ * [ VC: Standalone Document Declaration ]
+ * TODO The standalone document declaration must have the value "no"
+ * if any external markup declarations contain declarations of:
+ * - attributes with default values, if elements to which these
+ * attributes apply appear in the document without specifications
+ * of values for these attributes, or
+ * - entities (other than amp, lt, gt, apos, quot), if references
+ * to those entities appear in the document, or
+ * - attributes with values subject to normalization, where the
+ * attribute appears in the document with a value which will change
+ * as a result of normalization, or
+ * - element types with element content, if white space occurs directly
+ * within any instance of those types.
+ *
+ * Returns 1 if standalone, 0 otherwise
+ */
+
+int
+xmlParseSDDecl(xmlParserCtxtPtr ctxt) {
+ int standalone = -1;
+
+ SKIP_BLANKS;
+ if (CMP10(CUR_PTR, 's', 't', 'a', 'n', 'd', 'a', 'l', 'o', 'n', 'e')) {
+ SKIP(10);
+ SKIP_BLANKS;
+ if (RAW != '=') {
+ xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
+ return(standalone);
+ }
+ NEXT;
+ SKIP_BLANKS;
+ if (RAW == '\''){
+ NEXT;
+ if ((RAW == 'n') && (NXT(1) == 'o')) {
+ standalone = 0;
+ SKIP(2);
+ } else if ((RAW == 'y') && (NXT(1) == 'e') &&
+ (NXT(2) == 's')) {
+ standalone = 1;
+ SKIP(3);
+ } else {
+ xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
+ }
+ if (RAW != '\'') {
+ xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
+ } else
+ NEXT;
+ } else if (RAW == '"'){
+ NEXT;
+ if ((RAW == 'n') && (NXT(1) == 'o')) {
+ standalone = 0;
+ SKIP(2);
+ } else if ((RAW == 'y') && (NXT(1) == 'e') &&
+ (NXT(2) == 's')) {
+ standalone = 1;
+ SKIP(3);
+ } else {
+ xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
+ }
+ if (RAW != '"') {
+ xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
+ } else
+ NEXT;
+ } else {
+ xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
+ }
+ }
+ return(standalone);
+}
+
+/**
+ * xmlParseXMLDecl:
+ * @ctxt: an XML parser context
+ *
+ * parse an XML declaration header
+ *
+ * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
+ */
+
+void
+xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
+ xmlChar *version;
+
+ /*
+ * This value for standalone indicates that the document has an
+ * XML declaration but it does not have a standalone attribute.
+ * It will be overwritten later if a standalone attribute is found.
+ */
+ ctxt->input->standalone = -2;
+
+ /*
+ * We know that '<?xml' is here.
+ */
+ SKIP(5);
+
+ if (!IS_BLANK_CH(RAW)) {
+ xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
+ "Blank needed after '<?xml'\n");
+ }
+ SKIP_BLANKS;
+
+ /*
+ * We must have the VersionInfo here.
+ */
+ version = xmlParseVersionInfo(ctxt);
+ if (version == NULL) {
+ xmlFatalErr(ctxt, XML_ERR_VERSION_MISSING, NULL);
+ } else {
+ if (!xmlStrEqual(version, (const xmlChar *) XML_DEFAULT_VERSION)) {
+ /*
+ * TODO: Blueberry should be detected here
+ */
+ xmlWarningMsg(ctxt, XML_WAR_UNKNOWN_VERSION,
+ "Unsupported version '%s'\n",
+ version, NULL);
+ }
+ if (ctxt->version != NULL)
+ xmlFree((void *) ctxt->version);
+ ctxt->version = version;
+ }
+
+ /*
+ * We may have the encoding declaration
+ */
+ if (!IS_BLANK_CH(RAW)) {
+ if ((RAW == '?') && (NXT(1) == '>')) {
+ SKIP(2);
+ return;
+ }
+ xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
+ }
+ xmlParseEncodingDecl(ctxt);
+ if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
+ /*
+ * The XML REC instructs us to stop parsing right here
+ */
+ return;
+ }
+
+ /*
+ * We may have the standalone status.
+ */
+ if ((ctxt->input->encoding != NULL) && (!IS_BLANK_CH(RAW))) {
+ if ((RAW == '?') && (NXT(1) == '>')) {
+ SKIP(2);
+ return;
+ }
+ xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
+ }
+ SKIP_BLANKS;
+ ctxt->input->standalone = xmlParseSDDecl(ctxt);
+
+ SKIP_BLANKS;
+ if ((RAW == '?') && (NXT(1) == '>')) {
+ SKIP(2);
+ } else if (RAW == '>') {
+ /* Deprecated old WD ... */
+ xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
+ NEXT;
+ } else {
+ xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
+ MOVETO_ENDTAG(CUR_PTR);
+ NEXT;
+ }
+}
+
+/**
+ * xmlParseMisc:
+ * @ctxt: an XML parser context
+ *
+ * parse an XML Misc* optional field.
+ *
+ * [27] Misc ::= Comment | PI | S
+ */
+
+void
+xmlParseMisc(xmlParserCtxtPtr ctxt) {
+ while (((RAW == '<') && (NXT(1) == '?')) ||
+ (CMP4(CUR_PTR, '<', '!', '-', '-')) ||
+ IS_BLANK_CH(CUR)) {
+ if ((RAW == '<') && (NXT(1) == '?')) {
+ xmlParsePI(ctxt);
+ } else if (IS_BLANK_CH(CUR)) {
+ NEXT;
+ } else
+ xmlParseComment(ctxt);
+ }
+}
+
+/**
+ * xmlParseDocument:
+ * @ctxt: an XML parser context
+ *
+ * parse an XML document (and build a tree if using the standard SAX
+ * interface).
+ *
+ * [1] document ::= prolog element Misc*
+ *
+ * [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
+ *
+ * Returns 0, -1 in case of error. the parser context is augmented
+ * as a result of the parsing.
+ */
+
+int
+xmlParseDocument(xmlParserCtxtPtr ctxt) {
+ xmlChar start[4];
+ xmlCharEncoding enc;
+
+ xmlInitParser();
+
+ if ((ctxt == NULL) || (ctxt->input == NULL))
+ return(-1);
+
+ GROW;
+
+ /*
+ * SAX: detecting the level.
+ */
+ xmlDetectSAX2(ctxt);
+
+ /*
+ * SAX: beginning of the document processing.
+ */
+ if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
+ ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
+
+ if ((ctxt->encoding == (const xmlChar *)XML_CHAR_ENCODING_NONE) &&
+ ((ctxt->input->end - ctxt->input->cur) >= 4)) {
+ /*
+ * Get the 4 first bytes and decode the charset
+ * if enc != XML_CHAR_ENCODING_NONE
+ * plug some encoding conversion routines.
+ */
+ start[0] = RAW;
+ start[1] = NXT(1);
+ start[2] = NXT(2);
+ start[3] = NXT(3);
+ enc = xmlDetectCharEncoding(&start[0], 4);
+ if (enc != XML_CHAR_ENCODING_NONE) {
+ xmlSwitchEncoding(ctxt, enc);
+ }
+ }
+
+
+ if (CUR == 0) {
+ xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
+ }
+
+ /*
+ * Check for the XMLDecl in the Prolog.
+ */
+ GROW;
+ if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
+
+ /*
+ * Note that we will switch encoding on the fly.
+ */
+ xmlParseXMLDecl(ctxt);
+ if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
+ /*
+ * The XML REC instructs us to stop parsing right here
+ */
+ return(-1);
+ }
+ ctxt->standalone = ctxt->input->standalone;
+ SKIP_BLANKS;
+ } else {
+ ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
+ }
+ if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
+ ctxt->sax->startDocument(ctxt->userData);
+
+ /*
+ * The Misc part of the Prolog
+ */
+ GROW;
+ xmlParseMisc(ctxt);
+
+ /*
+ * Then possibly doc type declaration(s) and more Misc
+ * (doctypedecl Misc*)?
+ */
+ GROW;
+ if (CMP9(CUR_PTR, '<', '!', 'D', 'O', 'C', 'T', 'Y', 'P', 'E')) {
+
+ ctxt->inSubset = 1;
+ xmlParseDocTypeDecl(ctxt);
+ if (RAW == '[') {
+ ctxt->instate = XML_PARSER_DTD;
+ xmlParseInternalSubset(ctxt);
+ }
+
+ /*
+ * Create and update the external subset.
+ */
+ ctxt->inSubset = 2;
+ if ((ctxt->sax != NULL) && (ctxt->sax->externalSubset != NULL) &&
+ (!ctxt->disableSAX))
+ ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
+ ctxt->extSubSystem, ctxt->extSubURI);
+ ctxt->inSubset = 0;
+
+
+ ctxt->instate = XML_PARSER_PROLOG;
+ xmlParseMisc(ctxt);
+ }
+
+ /*
+ * Time to start parsing the tree itself
+ */
+ GROW;
+ if (RAW != '<') {
+ xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
+ "Start tag expected, '<' not found\n");
+ } else {
+ ctxt->instate = XML_PARSER_CONTENT;
+ xmlParseElement(ctxt);
+ ctxt->instate = XML_PARSER_EPILOG;
+
+
+ /*
+ * The Misc part at the end
+ */
+ xmlParseMisc(ctxt);
+
+ if (RAW != 0) {
+ xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
+ }
+ ctxt->instate = XML_PARSER_EOF;
+ }
+
+ /*
+ * SAX: end of the document processing.
+ */
+ if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
+ ctxt->sax->endDocument(ctxt->userData);
+
+ /*
+ * Remove locally kept entity definitions if the tree was not built
+ */
+ if ((ctxt->myDoc != NULL) &&
+ (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
+ xmlFreeDoc(ctxt->myDoc);
+ ctxt->myDoc = NULL;
+ }
+
+ if (! ctxt->wellFormed) {
+ ctxt->valid = 0;
+ return(-1);
+ }
+ return(0);
+}
+
+/**
+ * xmlParseExtParsedEnt:
+ * @ctxt: an XML parser context
+ *
+ * parse a general parsed entity
+ * An external general parsed entity is well-formed if it matches the
+ * production labeled extParsedEnt.
+ *
+ * [78] extParsedEnt ::= TextDecl? content
+ *
+ * Returns 0, -1 in case of error. the parser context is augmented
+ * as a result of the parsing.
+ */
+
+int
+xmlParseExtParsedEnt(xmlParserCtxtPtr ctxt) {
+ xmlChar start[4];
+ xmlCharEncoding enc;
+
+ if ((ctxt == NULL) || (ctxt->input == NULL))
+ return(-1);
+
+ xmlDefaultSAXHandlerInit();
+
+ xmlDetectSAX2(ctxt);
+
+ GROW;
+
+ /*
+ * SAX: beginning of the document processing.
+ */
+ if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
+ ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
+
+ /*
+ * Get the 4 first bytes and decode the charset
+ * if enc != XML_CHAR_ENCODING_NONE
+ * plug some encoding conversion routines.
+ */
+ 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 (CUR == 0) {
+ xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
+ }
+
+ /*
+ * Check for the XMLDecl in the Prolog.
+ */
+ GROW;
+ if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
+
+ /*
+ * Note that we will switch encoding on the fly.
+ */
+ xmlParseXMLDecl(ctxt);
+ if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
+ /*
+ * The XML REC instructs us to stop parsing right here
+ */
+ return(-1);
+ }
+ SKIP_BLANKS;
+ } else {
+ ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
+ }
+ if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
+ ctxt->sax->startDocument(ctxt->userData);
+
+ /*
+ * Doing validity checking on chunk doesn't make sense
+ */
+ ctxt->instate = XML_PARSER_CONTENT;
+ ctxt->validate = 0;
+ ctxt->loadsubset = 0;
+ ctxt->depth = 0;
+
+ xmlParseContent(ctxt);
+
+ if ((RAW == '<') && (NXT(1) == '/')) {
+ xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
+ } else if (RAW != 0) {
+ xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
+ }
+
+ /*
+ * SAX: end of the document processing.
+ */
+ if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
+ ctxt->sax->endDocument(ctxt->userData);
+
+ if (! ctxt->wellFormed) return(-1);
+ return(0);
+}
+
+#ifdef LIBXML_PUSH_ENABLED
+/************************************************************************
+ * *
+ * Progressive parsing interfaces *
+ * *
+ ************************************************************************/
+
+/**
+ * xmlParseLookupSequence:
+ * @ctxt: an XML parser context
+ * @first: the first char to lookup
+ * @next: the next char to lookup or zero
+ * @third: the next char to lookup or zero
+ *
+ * Try to find if a sequence (first, next, third) or just (first next) or
+ * (first) is available in the input stream.
+ * This function has a side effect of (possibly) incrementing ctxt->checkIndex
+ * to avoid rescanning sequences of bytes, it DOES change the state of the
+ * parser, do not use liberally.
+ *
+ * Returns the index to the current parsing point if the full sequence
+ * is available, -1 otherwise.
+ */
+static int
+xmlParseLookupSequence(xmlParserCtxtPtr ctxt, xmlChar first,
+ xmlChar next, xmlChar third) {
+ int base, len;
+ xmlParserInputPtr in;
+ const xmlChar *buf;
+
+ in = ctxt->input;
+ if (in == NULL) return(-1);
+ base = in->cur - in->base;
+ if (base < 0) return(-1);
+ if (ctxt->checkIndex > base)
+ base = ctxt->checkIndex;
+ if (in->buf == NULL) {
+ buf = in->base;
+ len = in->length;
+ } else {
+ buf = in->buf->buffer->content;
+ len = in->buf->buffer->use;
+ }
+ /* take into account the sequence length */
+ if (third) len -= 2;
+ else if (next) len --;
+ for (;base < len;base++) {
+ 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,
+ "PP: lookup '%c' found at %d\n",
+ first, base);
+ else if (third == 0)
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: lookup '%c%c' found at %d\n",
+ first, next, base);
+ else
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: 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,
+ "PP: lookup '%c' failed\n", first);
+ else if (third == 0)
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: lookup '%c%c' failed\n", first, next);
+ else
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: lookup '%c%c%c' failed\n", first, next, third);
+#endif
+ return(-1);
+}
+
+/**
+ * xmlParseGetLasts:
+ * @ctxt: an XML parser context
+ * @lastlt: pointer to store the last '<' from the input
+ * @lastgt: pointer to store the last '>' from the input
+ *
+ * Lookup the last < and > in the current chunk
+ */
+static void
+xmlParseGetLasts(xmlParserCtxtPtr ctxt, const xmlChar **lastlt,
+ const xmlChar **lastgt) {
+ const xmlChar *tmp;
+
+ if ((ctxt == NULL) || (lastlt == NULL) || (lastgt == NULL)) {
+ xmlGenericError(xmlGenericErrorContext,
+ "Internal error: xmlParseGetLasts\n");
+ return;
+ }
+ if ((ctxt->progressive != 0) && (ctxt->inputNr == 1)) {
+ tmp = ctxt->input->end;
+ tmp--;
+ while ((tmp >= ctxt->input->base) && (*tmp != '<')) tmp--;
+ if (tmp < ctxt->input->base) {
+ *lastlt = NULL;
+ *lastgt = NULL;
+ } else {
+ *lastlt = tmp;
+ tmp++;
+ while ((tmp < ctxt->input->end) && (*tmp != '>')) {
+ if (*tmp == '\'') {
+ tmp++;
+ while ((tmp < ctxt->input->end) && (*tmp != '\'')) tmp++;
+ if (tmp < ctxt->input->end) tmp++;
+ } else if (*tmp == '"') {
+ tmp++;
+ while ((tmp < ctxt->input->end) && (*tmp != '"')) tmp++;
+ if (tmp < ctxt->input->end) tmp++;
+ } else
+ tmp++;
+ }
+ if (tmp < ctxt->input->end)
+ *lastgt = tmp;
+ else {
+ tmp = *lastlt;
+ tmp--;
+ while ((tmp >= ctxt->input->base) && (*tmp != '>')) tmp--;
+ if (tmp >= ctxt->input->base)
+ *lastgt = tmp;
+ else
+ *lastgt = NULL;
+ }
+ }
+ } else {
+ *lastlt = NULL;
+ *lastgt = NULL;
+ }
+}
+/**
+ * xmlCheckCdataPush:
+ * @cur: pointer to the bock of characters
+ * @len: length of the block in bytes
+ *
+ * Check that the block of characters is okay as SCdata content [20]
+ *
+ * Returns the number of bytes to pass if okay, a negative index where an
+ * UTF-8 error occured otherwise
+ */
+static int
+xmlCheckCdataPush(const xmlChar *utf, int len) {
+ int ix;
+ unsigned char c;
+ int codepoint;
+
+ if ((utf == NULL) || (len <= 0))
+ return(0);
+
+ for (ix = 0; ix < len;) { /* string is 0-terminated */
+ c = utf[ix];
+ if ((c & 0x80) == 0x00) { /* 1-byte code, starts with 10 */
+ if (c >= 0x20)
+ ix++;
+ else if ((c == 0xA) || (c == 0xD) || (c == 0x9))
+ ix++;
+ else
+ return(-ix);
+ } else if ((c & 0xe0) == 0xc0) {/* 2-byte code, starts with 110 */
+ if (ix + 2 > len) return(ix);
+ if ((utf[ix+1] & 0xc0 ) != 0x80)
+ return(-ix);
+ codepoint = (utf[ix] & 0x1f) << 6;
+ codepoint |= utf[ix+1] & 0x3f;
+ if (!xmlIsCharQ(codepoint))
+ return(-ix);
+ ix += 2;
+ } else if ((c & 0xf0) == 0xe0) {/* 3-byte code, starts with 1110 */
+ if (ix + 3 > len) return(ix);
+ if (((utf[ix+1] & 0xc0) != 0x80) ||
+ ((utf[ix+2] & 0xc0) != 0x80))
+ return(-ix);
+ codepoint = (utf[ix] & 0xf) << 12;
+ codepoint |= (utf[ix+1] & 0x3f) << 6;
+ codepoint |= utf[ix+2] & 0x3f;
+ if (!xmlIsCharQ(codepoint))
+ return(-ix);
+ ix += 3;
+ } else if ((c & 0xf8) == 0xf0) {/* 4-byte code, starts with 11110 */
+ if (ix + 4 > len) return(ix);
+ if (((utf[ix+1] & 0xc0) != 0x80) ||
+ ((utf[ix+2] & 0xc0) != 0x80) ||
+ ((utf[ix+3] & 0xc0) != 0x80))
+ return(-ix);
+ codepoint = (utf[ix] & 0x7) << 18;
+ codepoint |= (utf[ix+1] & 0x3f) << 12;
+ codepoint |= (utf[ix+2] & 0x3f) << 6;
+ codepoint |= utf[ix+3] & 0x3f;
+ if (!xmlIsCharQ(codepoint))
+ return(-ix);
+ ix += 4;
+ } else /* unknown encoding */
+ return(-ix);
+ }
+ return(ix);
+}
+
+/**
+ * xmlParseTryOrFinish:
+ * @ctxt: an XML parser context
+ * @terminate: last chunk indicator
+ *
+ * Try to progress on parsing
+ *
+ * Returns zero if no parsing was possible
+ */
+static int
+xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
+ int ret = 0;
+ int avail, tlen;
+ xmlChar cur, next;
+ const xmlChar *lastlt, *lastgt;
+
+ if (ctxt->input == NULL)
+ return(0);
+
+#ifdef DEBUG_PUSH
+ switch (ctxt->instate) {
+ case XML_PARSER_EOF:
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: try EOF\n"); break;
+ case XML_PARSER_START:
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: try START\n"); break;
+ case XML_PARSER_MISC:
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: try MISC\n");break;
+ case XML_PARSER_COMMENT:
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: try COMMENT\n");break;
+ case XML_PARSER_PROLOG:
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: try PROLOG\n");break;
+ case XML_PARSER_START_TAG:
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: try START_TAG\n");break;
+ case XML_PARSER_CONTENT:
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: try CONTENT\n");break;
+ case XML_PARSER_CDATA_SECTION:
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: try CDATA_SECTION\n");break;
+ case XML_PARSER_END_TAG:
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: try END_TAG\n");break;
+ case XML_PARSER_ENTITY_DECL:
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: try ENTITY_DECL\n");break;
+ case XML_PARSER_ENTITY_VALUE:
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: try ENTITY_VALUE\n");break;
+ case XML_PARSER_ATTRIBUTE_VALUE:
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: try ATTRIBUTE_VALUE\n");break;
+ case XML_PARSER_DTD:
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: try DTD\n");break;
+ case XML_PARSER_EPILOG:
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: try EPILOG\n");break;
+ case XML_PARSER_PI:
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: try PI\n");break;
+ case XML_PARSER_IGNORE:
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: try IGNORE\n");break;
+ }
+#endif
+
+ if ((ctxt->input != NULL) &&
+ (ctxt->input->cur - ctxt->input->base > 4096)) {
+ xmlSHRINK(ctxt);
+ ctxt->checkIndex = 0;
+ }
+ xmlParseGetLasts(ctxt, &lastlt, &lastgt);
+
+ while (1) {
+ if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
+ return(0);
+
+
+ /*
+ * Pop-up of finished entities.
+ */
+ while ((RAW == 0) && (ctxt->inputNr > 1))
+ xmlPopInput(ctxt);
+
+ if (ctxt->input == NULL) break;
+ if (ctxt->input->buf == NULL)
+ avail = ctxt->input->length -
+ (ctxt->input->cur - ctxt->input->base);
+ else {
+ /*
+ * If we are operating on converted input, try to flush
+ * remainng chars to avoid them stalling in the non-converted
+ * buffer.
+ */
+ if ((ctxt->input->buf->raw != NULL) &&
+ (ctxt->input->buf->raw->use > 0)) {
+ int base = ctxt->input->base -
+ ctxt->input->buf->buffer->content;
+ int current = ctxt->input->cur - ctxt->input->base;
+
+ xmlParserInputBufferPush(ctxt->input->buf, 0, "");
+ ctxt->input->base = ctxt->input->buf->buffer->content + base;
+ ctxt->input->cur = ctxt->input->base + current;
+ ctxt->input->end =
+ &ctxt->input->buf->buffer->content[
+ ctxt->input->buf->buffer->use];
+ }
+ avail = ctxt->input->buf->buffer->use -
+ (ctxt->input->cur - ctxt->input->base);
+ }
+ if (avail < 1)
+ goto done;
+ switch (ctxt->instate) {
+ case XML_PARSER_EOF:
+ /*
+ * Document parsing is done !
+ */
+ goto done;
+ case XML_PARSER_START:
+ if (ctxt->charset == XML_CHAR_ENCODING_NONE) {
+ xmlChar start[4];
+ xmlCharEncoding enc;
+
+ /*
+ * Very first chars read from the document flow.
+ */
+ if (avail < 4)
+ goto done;
+
+ /*
+ * Get the 4 first bytes and decode the charset
+ * if enc != XML_CHAR_ENCODING_NONE
+ * plug some encoding conversion routines,
+ * else xmlSwitchEncoding will set to (default)
+ * UTF8.
+ */
+ start[0] = RAW;
+ start[1] = NXT(1);
+ start[2] = NXT(2);
+ start[3] = NXT(3);
+ enc = xmlDetectCharEncoding(start, 4);
+ xmlSwitchEncoding(ctxt, enc);
+ break;
+ }
+
+ if (avail < 2)
+ goto done;
+ cur = ctxt->input->cur[0];
+ next = ctxt->input->cur[1];
+ if (cur == 0) {
+ if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
+ ctxt->sax->setDocumentLocator(ctxt->userData,
+ &xmlDefaultSAXLocator);
+ xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
+ ctxt->instate = XML_PARSER_EOF;
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: entering EOF\n");
+#endif
+ if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
+ ctxt->sax->endDocument(ctxt->userData);
+ goto done;
+ }
+ if ((cur == '<') && (next == '?')) {
+ /* PI or XML decl */
+ if (avail < 5) return(ret);
+ if ((!terminate) &&
+ (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
+ return(ret);
+ if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
+ ctxt->sax->setDocumentLocator(ctxt->userData,
+ &xmlDefaultSAXLocator);
+ if ((ctxt->input->cur[2] == 'x') &&
+ (ctxt->input->cur[3] == 'm') &&
+ (ctxt->input->cur[4] == 'l') &&
+ (IS_BLANK_CH(ctxt->input->cur[5]))) {
+ ret += 5;
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: Parsing XML Decl\n");
+#endif
+ xmlParseXMLDecl(ctxt);
+ if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
+ /*
+ * The XML REC instructs us to stop parsing right
+ * here
+ */
+ ctxt->instate = XML_PARSER_EOF;
+ return(0);
+ }
+ ctxt->standalone = ctxt->input->standalone;
+ if ((ctxt->encoding == NULL) &&
+ (ctxt->input->encoding != NULL))
+ ctxt->encoding = xmlStrdup(ctxt->input->encoding);
+ if ((ctxt->sax) && (ctxt->sax->startDocument) &&
+ (!ctxt->disableSAX))
+ ctxt->sax->startDocument(ctxt->userData);
+ ctxt->instate = XML_PARSER_MISC;
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: entering MISC\n");
+#endif
+ } else {
+ ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
+ if ((ctxt->sax) && (ctxt->sax->startDocument) &&
+ (!ctxt->disableSAX))
+ ctxt->sax->startDocument(ctxt->userData);
+ ctxt->instate = XML_PARSER_MISC;
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: entering MISC\n");
+#endif
+ }
+ } else {
+ if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
+ ctxt->sax->setDocumentLocator(ctxt->userData,
+ &xmlDefaultSAXLocator);
+ ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
+ if (ctxt->version == NULL) {
+ xmlErrMemory(ctxt, NULL);
+ break;
+ }
+ if ((ctxt->sax) && (ctxt->sax->startDocument) &&
+ (!ctxt->disableSAX))
+ ctxt->sax->startDocument(ctxt->userData);
+ ctxt->instate = XML_PARSER_MISC;
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: entering MISC\n");
+#endif
+ }
+ break;
+ case XML_PARSER_START_TAG: {
+ const xmlChar *name;
+ const xmlChar *prefix;
+ const xmlChar *URI;
+ int nsNr = ctxt->nsNr;
+
+ if ((avail < 2) && (ctxt->inputNr == 1))
+ goto done;
+ cur = ctxt->input->cur[0];
+ if (cur != '<') {
+ xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
+ ctxt->instate = XML_PARSER_EOF;
+ if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
+ ctxt->sax->endDocument(ctxt->userData);
+ goto done;
+ }
+ if (!terminate) {
+ if (ctxt->progressive) {
+ /* > can be found unescaped in attribute values */
+ if ((lastgt == NULL) || (ctxt->input->cur >= lastgt))
+ goto done;
+ } else if (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0) {
+ goto done;
+ }
+ }
+ if (ctxt->spaceNr == 0)
+ spacePush(ctxt, -1);
+ else if (*ctxt->space == -2)
+ spacePush(ctxt, -1);
+ else
+ spacePush(ctxt, *ctxt->space);
+#ifdef LIBXML_SAX1_ENABLED
+ if (ctxt->sax2)
+#endif /* LIBXML_SAX1_ENABLED */
+ name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen);
+#ifdef LIBXML_SAX1_ENABLED
+ else
+ name = xmlParseStartTag(ctxt);
+#endif /* LIBXML_SAX1_ENABLED */
+ if (name == NULL) {
+ spacePop(ctxt);
+ ctxt->instate = XML_PARSER_EOF;
+ if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
+ ctxt->sax->endDocument(ctxt->userData);
+ goto done;
+ }
+#ifdef LIBXML_VALID_ENABLED
+ /*
+ * [ VC: Root Element Type ]
+ * The Name in the document type declaration must match
+ * the element type of the root element.
+ */
+ if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
+ ctxt->node && (ctxt->node == ctxt->myDoc->children))
+ ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
+#endif /* LIBXML_VALID_ENABLED */
+
+ /*
+ * Check for an Empty Element.
+ */
+ if ((RAW == '/') && (NXT(1) == '>')) {
+ SKIP(2);
+
+ if (ctxt->sax2) {
+ if ((ctxt->sax != NULL) &&
+ (ctxt->sax->endElementNs != NULL) &&
+ (!ctxt->disableSAX))
+ ctxt->sax->endElementNs(ctxt->userData, name,
+ prefix, URI);
+ if (ctxt->nsNr - nsNr > 0)
+ nsPop(ctxt, ctxt->nsNr - nsNr);
+#ifdef LIBXML_SAX1_ENABLED
+ } else {
+ if ((ctxt->sax != NULL) &&
+ (ctxt->sax->endElement != NULL) &&
+ (!ctxt->disableSAX))
+ ctxt->sax->endElement(ctxt->userData, name);
+#endif /* LIBXML_SAX1_ENABLED */
+ }
+ spacePop(ctxt);
+ if (ctxt->nameNr == 0) {
+ ctxt->instate = XML_PARSER_EPILOG;
+ } else {
+ ctxt->instate = XML_PARSER_CONTENT;
+ }
+ break;
+ }
+ if (RAW == '>') {
+ NEXT;
+ } else {
+ xmlFatalErrMsgStr(ctxt, XML_ERR_GT_REQUIRED,
+ "Couldn't find end of Start Tag %s\n",
+ name);
+ nodePop(ctxt);
+ spacePop(ctxt);
+ }
+ if (ctxt->sax2)
+ nameNsPush(ctxt, name, prefix, URI, ctxt->nsNr - nsNr);
+#ifdef LIBXML_SAX1_ENABLED
+ else
+ namePush(ctxt, name);
+#endif /* LIBXML_SAX1_ENABLED */
+
+ ctxt->instate = XML_PARSER_CONTENT;
+ break;
+ }
+ case XML_PARSER_CONTENT: {
+ const xmlChar *test;
+ unsigned int cons;
+ if ((avail < 2) && (ctxt->inputNr == 1))
+ goto done;
+ cur = ctxt->input->cur[0];
+ next = ctxt->input->cur[1];
+
+ test = CUR_PTR;
+ cons = ctxt->input->consumed;
+ if ((cur == '<') && (next == '/')) {
+ ctxt->instate = XML_PARSER_END_TAG;
+ break;
+ } else if ((cur == '<') && (next == '?')) {
+ if ((!terminate) &&
+ (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
+ goto done;
+ xmlParsePI(ctxt);
+ } else if ((cur == '<') && (next != '!')) {
+ ctxt->instate = XML_PARSER_START_TAG;
+ break;
+ } else if ((cur == '<') && (next == '!') &&
+ (ctxt->input->cur[2] == '-') &&
+ (ctxt->input->cur[3] == '-')) {
+ int term;
+
+ if (avail < 4)
+ goto done;
+ ctxt->input->cur += 4;
+ term = xmlParseLookupSequence(ctxt, '-', '-', '>');
+ ctxt->input->cur -= 4;
+ if ((!terminate) && (term < 0))
+ goto done;
+ xmlParseComment(ctxt);
+ ctxt->instate = XML_PARSER_CONTENT;
+ } else if ((cur == '<') && (ctxt->input->cur[1] == '!') &&
+ (ctxt->input->cur[2] == '[') &&
+ (ctxt->input->cur[3] == 'C') &&
+ (ctxt->input->cur[4] == 'D') &&
+ (ctxt->input->cur[5] == 'A') &&
+ (ctxt->input->cur[6] == 'T') &&
+ (ctxt->input->cur[7] == 'A') &&
+ (ctxt->input->cur[8] == '[')) {
+ SKIP(9);
+ ctxt->instate = XML_PARSER_CDATA_SECTION;
+ break;
+ } else if ((cur == '<') && (next == '!') &&
+ (avail < 9)) {
+ goto done;
+ } else if (cur == '&') {
+ if ((!terminate) &&
+ (xmlParseLookupSequence(ctxt, ';', 0, 0) < 0))
+ goto done;
+ xmlParseReference(ctxt);
+ } else {
+ /* TODO Avoid the extra copy, handle directly !!! */
+ /*
+ * Goal of the following test is:
+ * - minimize calls to the SAX 'character' callback
+ * when they are mergeable
+ * - handle an problem for isBlank when we only parse
+ * a sequence of blank chars and the next one is
+ * not available to check against '<' presence.
+ * - tries to homogenize the differences in SAX
+ * callbacks between the push and pull versions
+ * of the parser.
+ */
+ if ((ctxt->inputNr == 1) &&
+ (avail < XML_PARSER_BIG_BUFFER_SIZE)) {
+ if (!terminate) {
+ if (ctxt->progressive) {
+ if ((lastlt == NULL) ||
+ (ctxt->input->cur > lastlt))
+ goto done;
+ } else if (xmlParseLookupSequence(ctxt,
+ '<', 0, 0) < 0) {
+ goto done;
+ }
+ }
+ }
+ ctxt->checkIndex = 0;
+ xmlParseCharData(ctxt, 0);
+ }
+ /*
+ * Pop-up of finished entities.
+ */
+ while ((RAW == 0) && (ctxt->inputNr > 1))
+ xmlPopInput(ctxt);
+ if ((cons == ctxt->input->consumed) && (test == CUR_PTR)) {
+ xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
+ "detected an error in element content\n");
+ ctxt->instate = XML_PARSER_EOF;
+ break;
+ }
+ break;
+ }
+ case XML_PARSER_END_TAG:
+ if (avail < 2)
+ goto done;
+ if (!terminate) {
+ if (ctxt->progressive) {
+ /* > can be found unescaped in attribute values */
+ if ((lastgt == NULL) || (ctxt->input->cur >= lastgt))
+ goto done;
+ } else if (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0) {
+ goto done;
+ }
+ }
+ if (ctxt->sax2) {
+ xmlParseEndTag2(ctxt,
+ (void *) ctxt->pushTab[ctxt->nameNr * 3 - 3],
+ (void *) ctxt->pushTab[ctxt->nameNr * 3 - 2], 0,
+ (int) (long) ctxt->pushTab[ctxt->nameNr * 3 - 1], 0);
+ nameNsPop(ctxt);
+ }
+#ifdef LIBXML_SAX1_ENABLED
+ else
+ xmlParseEndTag1(ctxt, 0);
+#endif /* LIBXML_SAX1_ENABLED */
+ if (ctxt->nameNr == 0) {
+ ctxt->instate = XML_PARSER_EPILOG;
+ } else {
+ ctxt->instate = XML_PARSER_CONTENT;
+ }
+ break;
+ case XML_PARSER_CDATA_SECTION: {
+ /*
+ * The Push mode need to have the SAX callback for
+ * cdataBlock merge back contiguous callbacks.
+ */
+ int base;
+
+ base = xmlParseLookupSequence(ctxt, ']', ']', '>');
+ if (base < 0) {
+ if (avail >= XML_PARSER_BIG_BUFFER_SIZE + 2) {
+ int tmp;
+
+ tmp = xmlCheckCdataPush(ctxt->input->cur,
+ XML_PARSER_BIG_BUFFER_SIZE);
+ if (tmp < 0) {
+ tmp = -tmp;
+ ctxt->input->cur += tmp;
+ goto encoding_error;
+ }
+ if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
+ if (ctxt->sax->cdataBlock != NULL)
+ ctxt->sax->cdataBlock(ctxt->userData,
+ ctxt->input->cur, tmp);
+ else if (ctxt->sax->characters != NULL)
+ ctxt->sax->characters(ctxt->userData,
+ ctxt->input->cur, tmp);
+ }
+ SKIPL(tmp);
+ ctxt->checkIndex = 0;
+ }
+ goto done;
+ } else {
+ int tmp;
+
+ tmp = xmlCheckCdataPush(ctxt->input->cur, base);
+ if ((tmp < 0) || (tmp != base)) {
+ tmp = -tmp;
+ ctxt->input->cur += tmp;
+ goto encoding_error;
+ }
+ if ((ctxt->sax != NULL) && (base > 0) &&
+ (!ctxt->disableSAX)) {
+ if (ctxt->sax->cdataBlock != NULL)
+ ctxt->sax->cdataBlock(ctxt->userData,
+ ctxt->input->cur, base);
+ else if (ctxt->sax->characters != NULL)
+ ctxt->sax->characters(ctxt->userData,
+ ctxt->input->cur, base);
+ }
+ SKIPL(base + 3);
+ ctxt->checkIndex = 0;
+ ctxt->instate = XML_PARSER_CONTENT;
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: entering CONTENT\n");
+#endif
+ }
+ break;
+ }
+ case XML_PARSER_MISC:
+ SKIP_BLANKS;
+ if (ctxt->input->buf == NULL)
+ avail = ctxt->input->length -
+ (ctxt->input->cur - ctxt->input->base);
+ else
+ avail = ctxt->input->buf->buffer->use -
+ (ctxt->input->cur - ctxt->input->base);
+ if (avail < 2)
+ goto done;
+ cur = ctxt->input->cur[0];
+ next = ctxt->input->cur[1];
+ if ((cur == '<') && (next == '?')) {
+ if ((!terminate) &&
+ (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
+ goto done;
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: Parsing PI\n");
+#endif
+ xmlParsePI(ctxt);
+ } else if ((cur == '<') && (next == '!') &&
+ (ctxt->input->cur[2] == '-') &&
+ (ctxt->input->cur[3] == '-')) {
+ if ((!terminate) &&
+ (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
+ goto done;
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: Parsing Comment\n");
+#endif
+ xmlParseComment(ctxt);
+ ctxt->instate = XML_PARSER_MISC;
+ } else if ((cur == '<') && (next == '!') &&
+ (ctxt->input->cur[2] == 'D') &&
+ (ctxt->input->cur[3] == 'O') &&
+ (ctxt->input->cur[4] == 'C') &&
+ (ctxt->input->cur[5] == 'T') &&
+ (ctxt->input->cur[6] == 'Y') &&
+ (ctxt->input->cur[7] == 'P') &&
+ (ctxt->input->cur[8] == 'E')) {
+ if ((!terminate) &&
+ (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0))
+ goto done;
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: Parsing internal subset\n");
+#endif
+ ctxt->inSubset = 1;
+ xmlParseDocTypeDecl(ctxt);
+ if (RAW == '[') {
+ ctxt->instate = XML_PARSER_DTD;
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: entering DTD\n");
+#endif
+ } else {
+ /*
+ * Create and update the external subset.
+ */
+ ctxt->inSubset = 2;
+ if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
+ (ctxt->sax->externalSubset != NULL))
+ ctxt->sax->externalSubset(ctxt->userData,
+ ctxt->intSubName, ctxt->extSubSystem,
+ ctxt->extSubURI);
+ ctxt->inSubset = 0;
+ ctxt->instate = XML_PARSER_PROLOG;
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: entering PROLOG\n");
+#endif
+ }
+ } else if ((cur == '<') && (next == '!') &&
+ (avail < 9)) {
+ goto done;
+ } else {
+ ctxt->instate = XML_PARSER_START_TAG;
+ ctxt->progressive = 1;
+ xmlParseGetLasts(ctxt, &lastlt, &lastgt);
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: entering START_TAG\n");
+#endif
+ }
+ break;
+ case XML_PARSER_PROLOG:
+ SKIP_BLANKS;
+ if (ctxt->input->buf == NULL)
+ avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
+ else
+ avail = ctxt->input->buf->buffer->use - (ctxt->input->cur - ctxt->input->base);
+ if (avail < 2)
+ goto done;
+ cur = ctxt->input->cur[0];
+ next = ctxt->input->cur[1];
+ if ((cur == '<') && (next == '?')) {
+ if ((!terminate) &&
+ (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
+ goto done;
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: Parsing PI\n");
+#endif
+ xmlParsePI(ctxt);
+ } else if ((cur == '<') && (next == '!') &&
+ (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
+ if ((!terminate) &&
+ (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
+ goto done;
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: Parsing Comment\n");
+#endif
+ xmlParseComment(ctxt);
+ ctxt->instate = XML_PARSER_PROLOG;
+ } else if ((cur == '<') && (next == '!') &&
+ (avail < 4)) {
+ goto done;
+ } else {
+ ctxt->instate = XML_PARSER_START_TAG;
+ if (ctxt->progressive == 0)
+ ctxt->progressive = 1;
+ xmlParseGetLasts(ctxt, &lastlt, &lastgt);
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: entering START_TAG\n");
+#endif
+ }
+ break;
+ case XML_PARSER_EPILOG:
+ SKIP_BLANKS;
+ if (ctxt->input->buf == NULL)
+ avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
+ else
+ avail = ctxt->input->buf->buffer->use - (ctxt->input->cur - ctxt->input->base);
+ if (avail < 2)
+ goto done;
+ cur = ctxt->input->cur[0];
+ next = ctxt->input->cur[1];
+ if ((cur == '<') && (next == '?')) {
+ if ((!terminate) &&
+ (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
+ goto done;
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: Parsing PI\n");
+#endif
+ xmlParsePI(ctxt);
+ ctxt->instate = XML_PARSER_EPILOG;
+ } else if ((cur == '<') && (next == '!') &&
+ (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
+ if ((!terminate) &&
+ (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
+ goto done;
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: Parsing Comment\n");
+#endif
+ xmlParseComment(ctxt);
+ ctxt->instate = XML_PARSER_EPILOG;
+ } else if ((cur == '<') && (next == '!') &&
+ (avail < 4)) {
+ goto done;
+ } else {
+ xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
+ ctxt->instate = XML_PARSER_EOF;
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: entering EOF\n");
+#endif
+ if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
+ ctxt->sax->endDocument(ctxt->userData);
+ goto done;
+ }
+ break;
+ case XML_PARSER_DTD: {
+ /*
+ * Sorry but progressive parsing of the internal subset
+ * is not expected to be supported. We first check that
+ * the full content of the internal subset is available and
+ * the parsing is launched only at that point.
+ * Internal subset ends up with "']' S? '>'" in an unescaped
+ * section and not in a ']]>' sequence which are conditional
+ * sections (whoever argued to keep that crap in XML deserve
+ * a place in hell !).
+ */
+ int base, i;
+ xmlChar *buf;
+ xmlChar quote = 0;
+
+ base = ctxt->input->cur - ctxt->input->base;
+ if (base < 0) return(0);
+ if (ctxt->checkIndex > base)
+ base = ctxt->checkIndex;
+ buf = ctxt->input->buf->buffer->content;
+ for (;(unsigned int) base < ctxt->input->buf->buffer->use;
+ base++) {
+ if (quote != 0) {
+ if (buf[base] == quote)
+ quote = 0;
+ continue;
+ }
+ if ((quote == 0) && (buf[base] == '<')) {
+ int found = 0;
+ /* special handling of comments */
+ if (((unsigned int) base + 4 <
+ ctxt->input->buf->buffer->use) &&
+ (buf[base + 1] == '!') &&
+ (buf[base + 2] == '-') &&
+ (buf[base + 3] == '-')) {
+ for (;(unsigned int) base + 3 <
+ ctxt->input->buf->buffer->use; base++) {
+ if ((buf[base] == '-') &&
+ (buf[base + 1] == '-') &&
+ (buf[base + 2] == '>')) {
+ found = 1;
+ base += 2;
+ break;
+ }
+ }
+ if (!found) {
+#if 0
+ fprintf(stderr, "unfinished comment\n");
+#endif
+ break; /* for */
+ }
+ continue;
+ }
+ }
+ if (buf[base] == '"') {
+ quote = '"';
+ continue;
+ }
+ if (buf[base] == '\'') {
+ quote = '\'';
+ continue;
+ }
+ if (buf[base] == ']') {
+#if 0
+ fprintf(stderr, "%c%c%c%c: ", buf[base],
+ buf[base + 1], buf[base + 2], buf[base + 3]);
+#endif
+ if ((unsigned int) base +1 >=
+ ctxt->input->buf->buffer->use)
+ break;
+ if (buf[base + 1] == ']') {
+ /* conditional crap, skip both ']' ! */
+ base++;
+ continue;
+ }
+ for (i = 1;
+ (unsigned int) base + i < ctxt->input->buf->buffer->use;
+ i++) {
+ if (buf[base + i] == '>') {
+#if 0
+ fprintf(stderr, "found\n");
+#endif
+ goto found_end_int_subset;
+ }
+ if (!IS_BLANK_CH(buf[base + i])) {
+#if 0
+ fprintf(stderr, "not found\n");
+#endif
+ goto not_end_of_int_subset;
+ }
+ }
+#if 0
+ fprintf(stderr, "end of stream\n");
+#endif
+ break;
+
+ }
+not_end_of_int_subset:
+ continue; /* for */
+ }
+ /*
+ * We didn't found the end of the Internal subset
+ */
+#ifdef DEBUG_PUSH
+ if (next == 0)
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: lookup of int subset end filed\n");
+#endif
+ goto done;
+
+found_end_int_subset:
+ xmlParseInternalSubset(ctxt);
+ ctxt->inSubset = 2;
+ if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
+ (ctxt->sax->externalSubset != NULL))
+ ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
+ ctxt->extSubSystem, ctxt->extSubURI);
+ ctxt->inSubset = 0;
+ ctxt->instate = XML_PARSER_PROLOG;
+ ctxt->checkIndex = 0;
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: entering PROLOG\n");
+#endif
+ break;
+ }
+ case XML_PARSER_COMMENT:
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: internal error, state == COMMENT\n");
+ ctxt->instate = XML_PARSER_CONTENT;
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: entering CONTENT\n");
+#endif
+ break;
+ case XML_PARSER_IGNORE:
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: internal error, state == IGNORE");
+ ctxt->instate = XML_PARSER_DTD;
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: entering DTD\n");
+#endif
+ break;
+ case XML_PARSER_PI:
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: internal error, state == PI\n");
+ ctxt->instate = XML_PARSER_CONTENT;
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: entering CONTENT\n");
+#endif
+ break;
+ case XML_PARSER_ENTITY_DECL:
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: internal error, state == ENTITY_DECL\n");
+ ctxt->instate = XML_PARSER_DTD;
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: entering DTD\n");
+#endif
+ break;
+ case XML_PARSER_ENTITY_VALUE:
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: internal error, state == ENTITY_VALUE\n");
+ ctxt->instate = XML_PARSER_CONTENT;
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: entering DTD\n");
+#endif
+ break;
+ case XML_PARSER_ATTRIBUTE_VALUE:
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: internal error, state == ATTRIBUTE_VALUE\n");
+ ctxt->instate = XML_PARSER_START_TAG;
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: entering START_TAG\n");
+#endif
+ break;
+ case XML_PARSER_SYSTEM_LITERAL:
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: internal error, state == SYSTEM_LITERAL\n");
+ ctxt->instate = XML_PARSER_START_TAG;
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: entering START_TAG\n");
+#endif
+ break;
+ case XML_PARSER_PUBLIC_LITERAL:
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: internal error, state == PUBLIC_LITERAL\n");
+ ctxt->instate = XML_PARSER_START_TAG;
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext,
+ "PP: entering START_TAG\n");
+#endif
+ break;
+ }
+ }
+done:
+#ifdef DEBUG_PUSH
+ xmlGenericError(xmlGenericErrorContext, "PP: done %d\n", ret);
+#endif
+ return(ret);
+encoding_error:
+ {
+ 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]);
+ __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
+ "Input is not proper UTF-8, indicate encoding !\n%s",
+ BAD_CAST buffer, NULL);
+ }
+ return(0);
+}
+
+/**
+ * xmlParseChunk:
+ * @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
+xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
+ int terminate) {
+ int end_in_lf = 0;
+
+ if (ctxt == NULL)
+ return(XML_ERR_INTERNAL_ERROR);
+ if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
+ return(ctxt->errNo);
+ if (ctxt->instate == XML_PARSER_START)
+ xmlDetectSAX2(ctxt);
+ if ((size > 0) && (chunk != NULL) && (!terminate) &&
+ (chunk[size - 1] == '\r')) {
+ end_in_lf = 1;
+ size--;
+ }
+ 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, "PP: pushed %d\n", size);
+#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) {
+ /* TODO 2.6.0 */
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlParseChunk: encoder error\n");
+ return(XML_ERR_INVALID_ENCODING);
+ }
+ }
+ }
+ }
+ xmlParseTryOrFinish(ctxt, terminate);
+ if ((end_in_lf == 1) && (ctxt->input != NULL) &&
+ (ctxt->input->buf != NULL)) {
+ xmlParserInputBufferPush(ctxt->input->buf, 1, "\r");
+ }
+ if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
+ return(ctxt->errNo);
+ if (terminate) {
+ /*
+ * Check for termination
+ */
+ int avail = 0;
+
+ if (ctxt->input != NULL) {
+ if (ctxt->input->buf == NULL)
+ avail = ctxt->input->length -
+ (ctxt->input->cur - ctxt->input->base);
+ else
+ avail = ctxt->input->buf->buffer->use -
+ (ctxt->input->cur - ctxt->input->base);
+ }
+
+ if ((ctxt->instate != XML_PARSER_EOF) &&
+ (ctxt->instate != XML_PARSER_EPILOG)) {
+ xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
+ }
+ if ((ctxt->instate == XML_PARSER_EPILOG) && (avail > 0)) {
+ xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
+ }
+ 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);
+}
+
+/************************************************************************
+ * *
+ * I/O front end functions to the parser *
+ * *
+ ************************************************************************/
+
+/**
+ * xmlCreatePushParserCtxt:
+ * @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
+ *
+ * Create a parser context for using the XML parser in push mode.
+ * If @buffer and @size are non-NULL, the data is used to detect
+ * the encoding. The remaining characters will be parsed so they
+ * don't need to be fed in again through xmlParseChunk.
+ * 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
+ */
+
+xmlParserCtxtPtr
+xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
+ const char *chunk, int size, const char *filename) {
+ xmlParserCtxtPtr ctxt;
+ xmlParserInputPtr inputStream;
+ xmlParserInputBufferPtr buf;
+ xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
+
+ /*
+ * plug some encoding conversion routines
+ */
+ if ((chunk != NULL) && (size >= 4))
+ enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
+
+ buf = xmlAllocParserInputBuffer(enc);
+ if (buf == NULL) return(NULL);
+
+ ctxt = xmlNewParserCtxt();
+ if (ctxt == NULL) {
+ xmlErrMemory(NULL, "creating parser: out of memory\n");
+ xmlFreeParserInputBuffer(buf);
+ return(NULL);
+ }
+ ctxt->dictNames = 1;
+ ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 * sizeof(xmlChar *));
+ if (ctxt->pushTab == NULL) {
+ xmlErrMemory(ctxt, NULL);
+ xmlFreeParserInputBuffer(buf);
+ xmlFreeParserCtxt(ctxt);
+ return(NULL);
+ }
+ if (sax != NULL) {
+#ifdef LIBXML_SAX1_ENABLED
+ if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
+#endif /* LIBXML_SAX1_ENABLED */
+ xmlFree(ctxt->sax);
+ ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
+ if (ctxt->sax == NULL) {
+ xmlErrMemory(ctxt, NULL);
+ xmlFreeParserInputBuffer(buf);
+ xmlFreeParserCtxt(ctxt);
+ return(NULL);
+ }
+ memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
+ if (sax->initialized == XML_SAX2_MAGIC)
+ memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
+ else
+ memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
+ if (user_data != NULL)
+ ctxt->userData = user_data;
+ }
+ if (filename == NULL) {
+ ctxt->directory = NULL;
+ } else {
+ ctxt->directory = xmlParserGetDirectory(filename);
+ }
+
+ inputStream = xmlNewInputStream(ctxt);
+ if (inputStream == NULL) {
+ xmlFreeParserCtxt(ctxt);
+ xmlFreeParserInputBuffer(buf);
+ return(NULL);
+ }
+
+ if (filename == NULL)
+ inputStream->filename = NULL;
+ else {
+ inputStream->filename = (char *)
+ xmlCanonicPath((const xmlChar *) filename);
+ if (inputStream->filename == NULL) {
+ xmlFreeParserCtxt(ctxt);
+ xmlFreeParserInputBuffer(buf);
+ return(NULL);
+ }
+ }
+ 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 the caller didn't provide an initial 'chunk' for determining
+ * the encoding, we set the context to XML_CHAR_ENCODING_NONE so
+ * that it can be automatically determined later
+ */
+ if ((size == 0) || (chunk == NULL)) {
+ ctxt->charset = XML_CHAR_ENCODING_NONE;
+ } else if ((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, "PP: pushed %d\n", size);
+#endif
+ }
+
+ if (enc != XML_CHAR_ENCODING_NONE) {
+ xmlSwitchEncoding(ctxt, enc);
+ }
+
+ return(ctxt);
+}
+#endif /* LIBXML_PUSH_ENABLED */
+
+/**
+ * xmlStopParser:
+ * @ctxt: an XML parser context
+ *
+ * Blocks further parser processing
+ */
+void
+xmlStopParser(xmlParserCtxtPtr ctxt) {
+ if (ctxt == NULL)
+ return;
+ ctxt->instate = XML_PARSER_EOF;
+ ctxt->disableSAX = 1;
+ if (ctxt->input != NULL) {
+ ctxt->input->cur = BAD_CAST"";
+ ctxt->input->base = ctxt->input->cur;
+ }
+}
+
+/**
+ * xmlCreateIOParserCtxt:
+ * @sax: a SAX handler
+ * @user_data: The user data returned on SAX callbacks
+ * @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 parser context for using the XML parser with an existing
+ * I/O stream
+ *
+ * Returns the new parser context or NULL
+ */
+xmlParserCtxtPtr
+xmlCreateIOParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
+ xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
+ void *ioctx, xmlCharEncoding enc) {
+ xmlParserCtxtPtr ctxt;
+ xmlParserInputPtr inputStream;
+ xmlParserInputBufferPtr buf;
+
+ if (ioread == NULL) return(NULL);
+
+ buf = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, enc);
+ if (buf == NULL) return(NULL);
+
+ ctxt = xmlNewParserCtxt();
+ if (ctxt == NULL) {
+ xmlFreeParserInputBuffer(buf);
+ return(NULL);
+ }
+ if (sax != NULL) {
+#ifdef LIBXML_SAX1_ENABLED
+ if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
+#endif /* LIBXML_SAX1_ENABLED */
+ xmlFree(ctxt->sax);
+ ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
+ if (ctxt->sax == NULL) {
+ xmlErrMemory(ctxt, NULL);
+ xmlFreeParserCtxt(ctxt);
+ return(NULL);
+ }
+ memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
+ if (sax->initialized == XML_SAX2_MAGIC)
+ memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
+ else
+ memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
+ if (user_data != NULL)
+ ctxt->userData = user_data;
+ }
+
+ inputStream = xmlNewIOInputStream(ctxt, buf, enc);
+ if (inputStream == NULL) {
+ xmlFreeParserCtxt(ctxt);
+ return(NULL);
+ }
+ inputPush(ctxt, inputStream);
+
+ return(ctxt);
+}
+
+#ifdef LIBXML_VALID_ENABLED
+/************************************************************************
+ * *
+ * Front ends when parsing a DTD *
+ * *
+ ************************************************************************/
+
+/**
+ * xmlIOParseDTD:
+ * @sax: the SAX handler block or NULL
+ * @input: an Input Buffer
+ * @enc: the charset encoding if known
+ *
+ * Load and parse a DTD
+ *
+ * Returns the resulting xmlDtdPtr or NULL in case of error.
+ * @input will be freed by the function in any case.
+ */
+
+xmlDtdPtr
+xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
+ xmlCharEncoding enc) {
+ xmlDtdPtr ret = NULL;
+ xmlParserCtxtPtr ctxt;
+ xmlParserInputPtr pinput = NULL;
+ xmlChar start[4];
+
+ if (input == NULL)
+ return(NULL);
+
+ ctxt = xmlNewParserCtxt();
+ if (ctxt == NULL) {
+ xmlFreeParserInputBuffer(input);
+ return(NULL);
+ }
+
+ /*
+ * Set-up the SAX context
+ */
+ if (sax != NULL) {
+ if (ctxt->sax != NULL)
+ xmlFree(ctxt->sax);
+ ctxt->sax = sax;
+ ctxt->userData = ctxt;
+ }
+ xmlDetectSAX2(ctxt);
+
+ /*
+ * generate a parser input from the I/O handler
+ */
+
+ pinput = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
+ if (pinput == NULL) {
+ if (sax != NULL) ctxt->sax = NULL;
+ xmlFreeParserInputBuffer(input);
+ xmlFreeParserCtxt(ctxt);
+ return(NULL);
+ }
+
+ /*
+ * plug some encoding conversion routines here.
+ */
+ xmlPushInput(ctxt, pinput);
+ if (enc != XML_CHAR_ENCODING_NONE) {
+ xmlSwitchEncoding(ctxt, enc);
+ }
+
+ pinput->filename = NULL;
+ pinput->line = 1;
+ pinput->col = 1;
+ pinput->base = ctxt->input->cur;
+ pinput->cur = ctxt->input->cur;
+ pinput->free = NULL;
+
+ /*
+ * let's parse that entity knowing it's an external subset.
+ */
+ ctxt->inSubset = 2;
+ ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
+ ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
+ BAD_CAST "none", BAD_CAST "none");
+
+ if ((enc == XML_CHAR_ENCODING_NONE) &&
+ ((ctxt->input->end - ctxt->input->cur) >= 4)) {
+ /*
+ * Get the 4 first bytes and decode the charset
+ * if enc != XML_CHAR_ENCODING_NONE
+ * plug some encoding conversion routines.
+ */
+ 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);
+ }
+ }
+
+ xmlParseExternalSubset(ctxt, BAD_CAST "none", BAD_CAST "none");
+
+ if (ctxt->myDoc != NULL) {
+ if (ctxt->wellFormed) {
+ ret = ctxt->myDoc->extSubset;
+ ctxt->myDoc->extSubset = NULL;
+ if (ret != NULL) {
+ xmlNodePtr tmp;
+
+ ret->doc = NULL;
+ tmp = ret->children;
+ while (tmp != NULL) {
+ tmp->doc = NULL;
+ tmp = tmp->next;
+ }
+ }
+ } else {
+ ret = NULL;
+ }
+ xmlFreeDoc(ctxt->myDoc);
+ ctxt->myDoc = NULL;
+ }
+ if (sax != NULL) ctxt->sax = NULL;
+ xmlFreeParserCtxt(ctxt);
+
+ return(ret);
+}
+
+/**
+ * xmlSAXParseDTD:
+ * @sax: the SAX handler block
+ * @ExternalID: a NAME* containing the External ID of the DTD
+ * @SystemID: a NAME* containing the URL to the DTD
+ *
+ * Load and parse an external subset.
+ *
+ * Returns the resulting xmlDtdPtr or NULL in case of error.
+ */
+
+xmlDtdPtr
+xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
+ const xmlChar *SystemID) {
+ xmlDtdPtr ret = NULL;
+ xmlParserCtxtPtr ctxt;
+ xmlParserInputPtr input = NULL;
+ xmlCharEncoding enc;
+ xmlChar* systemIdCanonic;
+
+ if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL);
+
+ ctxt = xmlNewParserCtxt();
+ if (ctxt == NULL) {
+ return(NULL);
+ }
+
+ /*
+ * Set-up the SAX context
+ */
+ if (sax != NULL) {
+ if (ctxt->sax != NULL)
+ xmlFree(ctxt->sax);
+ ctxt->sax = sax;
+ ctxt->userData = ctxt;
+ }
+
+ /*
+ * Canonicalise the system ID
+ */
+ systemIdCanonic = xmlCanonicPath(SystemID);
+ if ((SystemID != NULL) && (systemIdCanonic == NULL)) {
+ xmlFreeParserCtxt(ctxt);
+ return(NULL);
+ }
+
+ /*
+ * Ask the Entity resolver to load the damn thing
+ */
+
+ if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
+ input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
+ systemIdCanonic);
+ if (input == NULL) {
+ if (sax != NULL) ctxt->sax = NULL;
+ xmlFreeParserCtxt(ctxt);
+ if (systemIdCanonic != NULL)
+ xmlFree(systemIdCanonic);
+ return(NULL);
+ }
+
+ /*
+ * plug some encoding conversion routines here.
+ */
+ xmlPushInput(ctxt, input);
+ if ((ctxt->input->end - ctxt->input->cur) >= 4) {
+ enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
+ xmlSwitchEncoding(ctxt, enc);
+ }
+
+ if (input->filename == NULL)
+ input->filename = (char *) systemIdCanonic;
+ else
+ xmlFree(systemIdCanonic);
+ input->line = 1;
+ input->col = 1;
+ input->base = ctxt->input->cur;
+ input->cur = ctxt->input->cur;
+ input->free = NULL;
+
+ /*
+ * let's parse that entity knowing it's an external subset.
+ */
+ ctxt->inSubset = 2;
+ ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
+ ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
+ ExternalID, SystemID);
+ xmlParseExternalSubset(ctxt, ExternalID, SystemID);
+
+ if (ctxt->myDoc != NULL) {
+ if (ctxt->wellFormed) {
+ ret = ctxt->myDoc->extSubset;
+ ctxt->myDoc->extSubset = NULL;
+ if (ret != NULL) {
+ xmlNodePtr tmp;
+
+ ret->doc = NULL;
+ tmp = ret->children;
+ while (tmp != NULL) {
+ tmp->doc = NULL;
+ tmp = tmp->next;
+ }
+ }
+ } else {
+ ret = NULL;
+ }
+ xmlFreeDoc(ctxt->myDoc);
+ ctxt->myDoc = NULL;
+ }
+ if (sax != NULL) ctxt->sax = NULL;
+ xmlFreeParserCtxt(ctxt);
+
+ return(ret);
+}
+
+
+/**
+ * xmlParseDTD:
+ * @ExternalID: a NAME* containing the External ID of the DTD
+ * @SystemID: a NAME* containing the URL to the DTD
+ *
+ * Load and parse an external subset.
+ *
+ * Returns the resulting xmlDtdPtr or NULL in case of error.
+ */
+
+xmlDtdPtr
+xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) {
+ return(xmlSAXParseDTD(NULL, ExternalID, SystemID));
+}
+#endif /* LIBXML_VALID_ENABLED */
+
+/************************************************************************
+ * *
+ * Front ends when parsing an Entity *
+ * *
+ ************************************************************************/
+
+/**
+ * xmlParseCtxtExternalEntity:
+ * @ctx: the existing parsing context
+ * @URL: the URL for the entity to load
+ * @ID: the System ID for the entity to load
+ * @lst: the return value for the set of parsed nodes
+ *
+ * Parse an external general entity within an existing parsing context
+ * An external general parsed entity is well-formed if it matches the
+ * production labeled extParsedEnt.
+ *
+ * [78] extParsedEnt ::= TextDecl? content
+ *
+ * Returns 0 if the entity is well formed, -1 in case of args problem and
+ * the parser error code otherwise
+ */
+
+int
+xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL,
+ const xmlChar *ID, xmlNodePtr *lst) {
+ xmlParserCtxtPtr ctxt;
+ xmlDocPtr newDoc;
+ xmlNodePtr newRoot;
+ xmlSAXHandlerPtr oldsax = NULL;
+ int ret = 0;
+ xmlChar start[4];
+ xmlCharEncoding enc;
+ xmlParserInputPtr inputStream;
+ char *directory = NULL;
+
+ if (ctx == NULL) return(-1);
+
+ if (ctx->depth > 40) {
+ return(XML_ERR_ENTITY_LOOP);
+ }
+
+ if (lst != NULL)
+ *lst = NULL;
+ if ((URL == NULL) && (ID == NULL))
+ return(-1);
+ if (ctx->myDoc == NULL) /* @@ relax but check for dereferences */
+ return(-1);
+
+ ctxt = xmlNewParserCtxt();
+ if (ctxt == NULL) {
+ return(-1);
+ }
+
+ ctxt->userData = ctxt;
+ ctxt->_private = ctx->_private;
+
+ inputStream = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt);
+ if (inputStream == NULL) {
+ xmlFreeParserCtxt(ctxt);
+ return(-1);
+ }
+
+ inputPush(ctxt, inputStream);
+
+ if ((ctxt->directory == NULL) && (directory == NULL))
+ directory = xmlParserGetDirectory((char *)URL);
+ if ((ctxt->directory == NULL) && (directory != NULL))
+ ctxt->directory = directory;
+
+ oldsax = ctxt->sax;
+ ctxt->sax = ctx->sax;
+ xmlDetectSAX2(ctxt);
+ newDoc = xmlNewDoc(BAD_CAST "1.0");
+ if (newDoc == NULL) {
+ xmlFreeParserCtxt(ctxt);
+ return(-1);
+ }
+ if (ctx->myDoc->dict) {
+ newDoc->dict = ctx->myDoc->dict;
+ xmlDictReference(newDoc->dict);
+ }
+ if (ctx->myDoc != NULL) {
+ newDoc->intSubset = ctx->myDoc->intSubset;
+ newDoc->extSubset = ctx->myDoc->extSubset;
+ }
+ if (ctx->myDoc->URL != NULL) {
+ newDoc->URL = xmlStrdup(ctx->myDoc->URL);
+ }
+ newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
+ if (newRoot == NULL) {
+ ctxt->sax = oldsax;
+ xmlFreeParserCtxt(ctxt);
+ newDoc->intSubset = NULL;
+ newDoc->extSubset = NULL;
+ xmlFreeDoc(newDoc);
+ return(-1);
+ }
+ xmlAddChild((xmlNodePtr) newDoc, newRoot);
+ nodePush(ctxt, newDoc->children);
+ if (ctx->myDoc == NULL) {
+ ctxt->myDoc = newDoc;
+ } else {
+ ctxt->myDoc = ctx->myDoc;
+ newDoc->children->doc = ctx->myDoc;
+ }
+
+ /*
+ * Get the 4 first bytes and decode the charset
+ * if enc != XML_CHAR_ENCODING_NONE
+ * plug some encoding conversion routines.
+ */
+ 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);
+ }
+ }
+
+ /*
+ * Parse a possible text declaration first
+ */
+ if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
+ xmlParseTextDecl(ctxt);
+ }
+
+ /*
+ * Doing validity checking on chunk doesn't make sense
+ */
+ ctxt->instate = XML_PARSER_CONTENT;
+ ctxt->validate = ctx->validate;
+ ctxt->valid = ctx->valid;
+ ctxt->loadsubset = ctx->loadsubset;
+ ctxt->depth = ctx->depth + 1;
+ ctxt->replaceEntities = ctx->replaceEntities;
+ if (ctxt->validate) {
+ ctxt->vctxt.error = ctx->vctxt.error;
+ ctxt->vctxt.warning = ctx->vctxt.warning;
+ } else {
+ ctxt->vctxt.error = NULL;
+ ctxt->vctxt.warning = NULL;
+ }
+ ctxt->vctxt.nodeTab = NULL;
+ ctxt->vctxt.nodeNr = 0;
+ ctxt->vctxt.nodeMax = 0;
+ ctxt->vctxt.node = NULL;
+ if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
+ ctxt->dict = ctx->dict;
+ 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);
+ ctxt->dictNames = ctx->dictNames;
+ ctxt->attsDefault = ctx->attsDefault;
+ ctxt->attsSpecial = ctx->attsSpecial;
+ ctxt->linenumbers = ctx->linenumbers;
+
+ xmlParseContent(ctxt);
+
+ ctx->validate = ctxt->validate;
+ ctx->valid = ctxt->valid;
+ if ((RAW == '<') && (NXT(1) == '/')) {
+ xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
+ } else if (RAW != 0) {
+ xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
+ }
+ if (ctxt->node != newDoc->children) {
+ xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
+ }
+
+ if (!ctxt->wellFormed) {
+ if (ctxt->errNo == 0)
+ ret = 1;
+ else
+ ret = ctxt->errNo;
+ } else {
+ if (lst != NULL) {
+ xmlNodePtr cur;
+
+ /*
+ * Return the newly created nodeset after unlinking it from
+ * they pseudo parent.
+ */
+ cur = newDoc->children->children;
+ *lst = cur;
+ while (cur != NULL) {
+ cur->parent = NULL;
+ cur = cur->next;
+ }
+ newDoc->children->children = NULL;
+ }
+ ret = 0;
+ }
+ ctxt->sax = oldsax;
+ ctxt->dict = NULL;
+ ctxt->attsDefault = NULL;
+ ctxt->attsSpecial = NULL;
+ xmlFreeParserCtxt(ctxt);
+ newDoc->intSubset = NULL;
+ newDoc->extSubset = NULL;
+ xmlFreeDoc(newDoc);
+
+ return(ret);
+}
+
+/**
+ * xmlParseExternalEntityPrivate:
+ * @doc: the document the chunk pertains to
+ * @oldctxt: the previous parser context if available
+ * @sax: the SAX handler bloc (possibly NULL)
+ * @user_data: The user data returned on SAX callbacks (possibly NULL)
+ * @depth: Used for loop detection, use 0
+ * @URL: the URL for the entity to load
+ * @ID: the System ID for the entity to load
+ * @list: the return value for the set of parsed nodes
+ *
+ * Private version of xmlParseExternalEntity()
+ *
+ * Returns 0 if the entity is well formed, -1 in case of args problem and
+ * the parser error code otherwise
+ */
+
+static xmlParserErrors
+xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
+ xmlSAXHandlerPtr sax,
+ void *user_data, int depth, const xmlChar *URL,
+ const xmlChar *ID, xmlNodePtr *list) {
+ xmlParserCtxtPtr ctxt;
+ xmlDocPtr newDoc;
+ xmlNodePtr newRoot;
+ xmlSAXHandlerPtr oldsax = NULL;
+ xmlParserErrors ret = XML_ERR_OK;
+ xmlChar start[4];
+ xmlCharEncoding enc;
+
+ if (depth > 40) {
+ return(XML_ERR_ENTITY_LOOP);
+ }
+
+
+
+ if (list != NULL)
+ *list = NULL;
+ if ((URL == NULL) && (ID == NULL))
+ return(XML_ERR_INTERNAL_ERROR);
+ if (doc == NULL)
+ return(XML_ERR_INTERNAL_ERROR);
+
+
+ ctxt = xmlCreateEntityParserCtxt(URL, ID, NULL);
+ if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
+ ctxt->userData = ctxt;
+ if (oldctxt != NULL) {
+ ctxt->_private = oldctxt->_private;
+ ctxt->loadsubset = oldctxt->loadsubset;
+ ctxt->validate = oldctxt->validate;
+ ctxt->external = oldctxt->external;
+ ctxt->record_info = oldctxt->record_info;
+ ctxt->node_seq.maximum = oldctxt->node_seq.maximum;
+ ctxt->node_seq.length = oldctxt->node_seq.length;
+ ctxt->node_seq.buffer = oldctxt->node_seq.buffer;
+ } else {
+ /*
+ * Doing validity checking on chunk without context
+ * doesn't make sense
+ */
+ ctxt->_private = NULL;
+ ctxt->validate = 0;
+ ctxt->external = 2;
+ ctxt->loadsubset = 0;
+ }
+ if (sax != NULL) {
+ oldsax = ctxt->sax;
+ ctxt->sax = sax;
+ if (user_data != NULL)
+ ctxt->userData = user_data;
+ }
+ xmlDetectSAX2(ctxt);
+ newDoc = xmlNewDoc(BAD_CAST "1.0");
+ if (newDoc == NULL) {
+ ctxt->node_seq.maximum = 0;
+ ctxt->node_seq.length = 0;
+ ctxt->node_seq.buffer = NULL;
+ xmlFreeParserCtxt(ctxt);
+ return(XML_ERR_INTERNAL_ERROR);
+ }
+ newDoc->intSubset = doc->intSubset;
+ newDoc->extSubset = doc->extSubset;
+ newDoc->dict = doc->dict;
+ xmlDictReference(newDoc->dict);
+
+ if (doc->URL != NULL) {
+ newDoc->URL = xmlStrdup(doc->URL);
+ }
+ newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
+ if (newRoot == NULL) {
+ if (sax != NULL)
+ ctxt->sax = oldsax;
+ ctxt->node_seq.maximum = 0;
+ ctxt->node_seq.length = 0;
+ ctxt->node_seq.buffer = NULL;
+ xmlFreeParserCtxt(ctxt);
+ newDoc->intSubset = NULL;
+ newDoc->extSubset = NULL;
+ xmlFreeDoc(newDoc);
+ return(XML_ERR_INTERNAL_ERROR);
+ }
+ xmlAddChild((xmlNodePtr) newDoc, newRoot);
+ nodePush(ctxt, newDoc->children);
+ ctxt->myDoc = doc;
+ newRoot->doc = doc;
+
+ /*
+ * Get the 4 first bytes and decode the charset
+ * if enc != XML_CHAR_ENCODING_NONE
+ * plug some encoding conversion routines.
+ */
+ 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);
+ }
+ }
+
+ /*
+ * Parse a possible text declaration first
+ */
+ if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
+ xmlParseTextDecl(ctxt);
+ }
+
+ ctxt->instate = XML_PARSER_CONTENT;
+ ctxt->depth = depth;
+
+ xmlParseContent(ctxt);
+
+ if ((RAW == '<') && (NXT(1) == '/')) {
+ xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
+ } else if (RAW != 0) {
+ xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
+ }
+ if (ctxt->node != newDoc->children) {
+ xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
+ }
+
+ if (!ctxt->wellFormed) {
+ if (ctxt->errNo == 0)
+ ret = XML_ERR_INTERNAL_ERROR;
+ else
+ ret = (xmlParserErrors)ctxt->errNo;
+ } else {
+ if (list != NULL) {
+ xmlNodePtr cur;
+
+ /*
+ * Return the newly created nodeset after unlinking it from
+ * they pseudo parent.
+ */
+ cur = newDoc->children->children;
+ *list = cur;
+ while (cur != NULL) {
+ cur->parent = NULL;
+ cur = cur->next;
+ }
+ newDoc->children->children = NULL;
+ }
+ ret = XML_ERR_OK;
+ }
+ if (sax != NULL)
+ ctxt->sax = oldsax;
+ oldctxt->node_seq.maximum = ctxt->node_seq.maximum;
+ oldctxt->node_seq.length = ctxt->node_seq.length;
+ oldctxt->node_seq.buffer = ctxt->node_seq.buffer;
+ ctxt->node_seq.maximum = 0;
+ ctxt->node_seq.length = 0;
+ ctxt->node_seq.buffer = NULL;
+ xmlFreeParserCtxt(ctxt);
+ newDoc->intSubset = NULL;
+ newDoc->extSubset = NULL;
+ xmlFreeDoc(newDoc);
+
+ return(ret);
+}
+
+#ifdef LIBXML_SAX1_ENABLED
+/**
+ * xmlParseExternalEntity:
+ * @doc: the document the chunk pertains to
+ * @sax: the SAX handler bloc (possibly NULL)
+ * @user_data: The user data returned on SAX callbacks (possibly NULL)
+ * @depth: Used for loop detection, use 0
+ * @URL: the URL for the entity to load
+ * @ID: the System ID for the entity to load
+ * @lst: the return value for the set of parsed nodes
+ *
+ * Parse an external general entity
+ * An external general parsed entity is well-formed if it matches the
+ * production labeled extParsedEnt.
+ *
+ * [78] extParsedEnt ::= TextDecl? content
+ *
+ * Returns 0 if the entity is well formed, -1 in case of args problem and
+ * the parser error code otherwise
+ */
+
+int
+xmlParseExternalEntity(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data,
+ int depth, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *lst) {
+ return(xmlParseExternalEntityPrivate(doc, NULL, sax, user_data, depth, URL,
+ ID, lst));
+}
+
+/**
+ * xmlParseBalancedChunkMemory:
+ * @doc: the document the chunk pertains to
+ * @sax: the SAX handler bloc (possibly NULL)
+ * @user_data: The user data returned on SAX callbacks (possibly NULL)
+ * @depth: Used for loop detection, use 0
+ * @string: the input string in UTF8 or ISO-Latin (zero terminated)
+ * @lst: the return value for the set of parsed nodes
+ *
+ * Parse a well-balanced chunk of an XML document
+ * called by the parser
+ * The allowed sequence for the Well Balanced Chunk is the one defined by
+ * the content production in the XML grammar:
+ *
+ * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
+ *
+ * Returns 0 if the chunk is well balanced, -1 in case of args problem and
+ * the parser error code otherwise
+ */
+
+int
+xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlSAXHandlerPtr sax,
+ void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst) {
+ return xmlParseBalancedChunkMemoryRecover( doc, sax, user_data,
+ depth, string, lst, 0 );
+}
+#endif /* LIBXML_SAX1_ENABLED */
+
+/**
+ * xmlParseBalancedChunkMemoryInternal:
+ * @oldctxt: the existing parsing context
+ * @string: the input string in UTF8 or ISO-Latin (zero terminated)
+ * @user_data: the user data field for the parser context
+ * @lst: the return value for the set of parsed nodes
+ *
+ *
+ * Parse a well-balanced chunk of an XML document
+ * called by the parser
+ * The allowed sequence for the Well Balanced Chunk is the one defined by
+ * the content production in the XML grammar:
+ *
+ * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
+ *
+ * Returns XML_ERR_OK if the chunk is well balanced, and the parser
+ * error code otherwise
+ *
+ * In case recover is set to 1, the nodelist will not be empty even if
+ * the parsed chunk is not well balanced.
+ */
+static xmlParserErrors
+xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
+ const xmlChar *string, void *user_data, xmlNodePtr *lst) {
+ xmlParserCtxtPtr ctxt;
+ xmlDocPtr newDoc = NULL;
+ xmlNodePtr newRoot;
+ xmlSAXHandlerPtr oldsax = NULL;
+ xmlNodePtr content = NULL;
+ xmlNodePtr last = NULL;
+ int size;
+ xmlParserErrors ret = XML_ERR_OK;
+
+ if (oldctxt->depth > 40) {
+ return(XML_ERR_ENTITY_LOOP);
+ }
+
+
+ if (lst != NULL)
+ *lst = NULL;
+ if (string == NULL)
+ return(XML_ERR_INTERNAL_ERROR);
+
+ size = xmlStrlen(string);
+
+ ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
+ if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
+ if (user_data != NULL)
+ ctxt->userData = user_data;
+ else
+ ctxt->userData = ctxt;
+ if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
+ ctxt->dict = oldctxt->dict;
+ 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);
+
+ oldsax = ctxt->sax;
+ ctxt->sax = oldctxt->sax;
+ xmlDetectSAX2(ctxt);
+ ctxt->replaceEntities = oldctxt->replaceEntities;
+ ctxt->options = oldctxt->options;
+
+ ctxt->_private = oldctxt->_private;
+ if (oldctxt->myDoc == NULL) {
+ newDoc = xmlNewDoc(BAD_CAST "1.0");
+ if (newDoc == NULL) {
+ ctxt->sax = oldsax;
+ ctxt->dict = NULL;
+ xmlFreeParserCtxt(ctxt);
+ return(XML_ERR_INTERNAL_ERROR);
+ }
+ newDoc->dict = ctxt->dict;
+ xmlDictReference(newDoc->dict);
+ ctxt->myDoc = newDoc;
+ } else {
+ ctxt->myDoc = oldctxt->myDoc;
+ content = ctxt->myDoc->children;
+ last = ctxt->myDoc->last;
+ }
+ newRoot = xmlNewDocNode(ctxt->myDoc, NULL, BAD_CAST "pseudoroot", NULL);
+ if (newRoot == NULL) {
+ ctxt->sax = oldsax;
+ ctxt->dict = NULL;
+ xmlFreeParserCtxt(ctxt);
+ if (newDoc != NULL) {
+ xmlFreeDoc(newDoc);
+ }
+ return(XML_ERR_INTERNAL_ERROR);
+ }
+ ctxt->myDoc->children = NULL;
+ ctxt->myDoc->last = NULL;
+ xmlAddChild((xmlNodePtr) ctxt->myDoc, newRoot);
+ nodePush(ctxt, ctxt->myDoc->children);
+ ctxt->instate = XML_PARSER_CONTENT;
+ ctxt->depth = oldctxt->depth + 1;
+
+ ctxt->validate = 0;
+ ctxt->loadsubset = oldctxt->loadsubset;
+ if ((oldctxt->validate) || (oldctxt->replaceEntities != 0)) {
+ /*
+ * ID/IDREF registration will be done in xmlValidateElement below
+ */
+ ctxt->loadsubset |= XML_SKIP_IDS;
+ }
+ ctxt->dictNames = oldctxt->dictNames;
+ ctxt->attsDefault = oldctxt->attsDefault;
+ ctxt->attsSpecial = oldctxt->attsSpecial;
+
+ xmlParseContent(ctxt);
+ if ((RAW == '<') && (NXT(1) == '/')) {
+ xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
+ } else if (RAW != 0) {
+ xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
+ }
+ if (ctxt->node != ctxt->myDoc->children) {
+ xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
+ }
+
+ if (!ctxt->wellFormed) {
+ if (ctxt->errNo == 0)
+ ret = XML_ERR_INTERNAL_ERROR;
+ else
+ ret = (xmlParserErrors)ctxt->errNo;
+ } else {
+ ret = XML_ERR_OK;
+ }
+
+ if ((lst != NULL) && (ret == XML_ERR_OK)) {
+ xmlNodePtr cur;
+
+ /*
+ * Return the newly created nodeset after unlinking it from
+ * they pseudo parent.
+ */
+ cur = ctxt->myDoc->children->children;
+ *lst = cur;
+ while (cur != NULL) {
+#ifdef LIBXML_VALID_ENABLED
+ if ((oldctxt->validate) && (oldctxt->wellFormed) &&
+ (oldctxt->myDoc) && (oldctxt->myDoc->intSubset) &&
+ (cur->type == XML_ELEMENT_NODE)) {
+ oldctxt->valid &= xmlValidateElement(&oldctxt->vctxt,
+ oldctxt->myDoc, cur);
+ }
+#endif /* LIBXML_VALID_ENABLED */
+ cur->parent = NULL;
+ cur = cur->next;
+ }
+ ctxt->myDoc->children->children = NULL;
+ }
+ if (ctxt->myDoc != NULL) {
+ xmlFreeNode(ctxt->myDoc->children);
+ ctxt->myDoc->children = content;
+ ctxt->myDoc->last = last;
+ }
+
+ ctxt->sax = oldsax;
+ ctxt->dict = NULL;
+ ctxt->attsDefault = NULL;
+ ctxt->attsSpecial = NULL;
+ xmlFreeParserCtxt(ctxt);
+ if (newDoc != NULL) {
+ xmlFreeDoc(newDoc);
+ }
+
+ return(ret);
+}
+
+/**
+ * xmlParseInNodeContext:
+ * @node: the context node
+ * @data: the input string
+ * @datalen: the input string length in bytes
+ * @options: a combination of xmlParserOption
+ * @lst: the return value for the set of parsed nodes
+ *
+ * Parse a well-balanced chunk of an XML document
+ * within the context (DTD, namespaces, etc ...) of the given node.
+ *
+ * The allowed sequence for the data is a Well Balanced Chunk defined by
+ * the content production in the XML grammar:
+ *
+ * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
+ *
+ * Returns XML_ERR_OK if the chunk is well balanced, and the parser
+ * error code otherwise
+ */
+xmlParserErrors
+xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
+ int options, xmlNodePtr *lst) {
+#ifdef SAX2
+ xmlParserCtxtPtr ctxt;
+ xmlDocPtr doc = NULL;
+ xmlNodePtr fake, cur;
+ int nsnr = 0;
+
+ xmlParserErrors ret = XML_ERR_OK;
+
+ /*
+ * check all input parameters, grab the document
+ */
+ if ((lst == NULL) || (node == NULL) || (data == NULL) || (datalen < 0))
+ return(XML_ERR_INTERNAL_ERROR);
+ 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:
+ case XML_DOCUMENT_NODE:
+ case XML_HTML_DOCUMENT_NODE:
+ break;
+ default:
+ return(XML_ERR_INTERNAL_ERROR);
+
+ }
+ while ((node != NULL) && (node->type != XML_ELEMENT_NODE) &&
+ (node->type != XML_DOCUMENT_NODE) &&
+ (node->type != XML_HTML_DOCUMENT_NODE))
+ node = node->parent;
+ if (node == NULL)
+ return(XML_ERR_INTERNAL_ERROR);
+ if (node->type == XML_ELEMENT_NODE)
+ doc = node->doc;
+ else
+ doc = (xmlDocPtr) node;
+ if (doc == NULL)
+ return(XML_ERR_INTERNAL_ERROR);
+
+ /*
+ * allocate a context and set-up everything not related to the
+ * node position in the tree
+ */
+ if (doc->type == XML_DOCUMENT_NODE)
+ ctxt = xmlCreateMemoryParserCtxt((char *) data, datalen);
+#ifdef LIBXML_HTML_ENABLED
+ else if (doc->type == XML_HTML_DOCUMENT_NODE)
+ ctxt = htmlCreateMemoryParserCtxt((char *) data, datalen);
+#endif
+ else
+ return(XML_ERR_INTERNAL_ERROR);
+
+ if (ctxt == NULL)
+ return(XML_ERR_NO_MEMORY);
+ fake = xmlNewComment(NULL);
+ if (fake == NULL) {
+ xmlFreeParserCtxt(ctxt);
+ return(XML_ERR_NO_MEMORY);
+ }
+ xmlAddChild(node, fake);
+
+ /*
+ * Use input doc's dict if present, else assure XML_PARSE_NODICT is set.
+ * We need a dictionary for xmlDetectSAX2, so if there's no doc dict
+ * we must wait until the last moment to free the original one.
+ */
+ if (doc->dict != NULL) {
+ if (ctxt->dict != NULL)
+ xmlDictFree(ctxt->dict);
+ ctxt->dict = doc->dict;
+ } else
+ options |= XML_PARSE_NODICT;
+
+ xmlCtxtUseOptions(ctxt, options);
+ xmlDetectSAX2(ctxt);
+ ctxt->myDoc = doc;
+
+ if (node->type == XML_ELEMENT_NODE) {
+ nodePush(ctxt, node);
+ /*
+ * initialize the SAX2 namespaces stack
+ */
+ cur = node;
+ while ((cur != NULL) && (cur->type == XML_ELEMENT_NODE)) {
+ xmlNsPtr ns = cur->nsDef;
+ const xmlChar *iprefix, *ihref;
+
+ while (ns != NULL) {
+ if (ctxt->dict) {
+ iprefix = xmlDictLookup(ctxt->dict, ns->prefix, -1);
+ ihref = xmlDictLookup(ctxt->dict, ns->href, -1);
+ } else {
+ iprefix = ns->prefix;
+ ihref = ns->href;
+ }
+
+ if (xmlGetNamespace(ctxt, iprefix) == NULL) {
+ nsPush(ctxt, iprefix, ihref);
+ nsnr++;
+ }
+ ns = ns->next;
+ }
+ cur = cur->parent;
+ }
+ ctxt->instate = XML_PARSER_CONTENT;
+ }
+
+ if ((ctxt->validate) || (ctxt->replaceEntities != 0)) {
+ /*
+ * ID/IDREF registration will be done in xmlValidateElement below
+ */
+ ctxt->loadsubset |= XML_SKIP_IDS;
+ }
+
+#ifdef LIBXML_HTML_ENABLED
+ if (doc->type == XML_HTML_DOCUMENT_NODE)
+ __htmlParseContent(ctxt);
+ else
+#endif
+ xmlParseContent(ctxt);
+
+ nsPop(ctxt, nsnr);
+ if ((RAW == '<') && (NXT(1) == '/')) {
+ xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
+ } else if (RAW != 0) {
+ xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
+ }
+ if ((ctxt->node != NULL) && (ctxt->node != node)) {
+ xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
+ ctxt->wellFormed = 0;
+ }
+
+ if (!ctxt->wellFormed) {
+ if (ctxt->errNo == 0)
+ ret = XML_ERR_INTERNAL_ERROR;
+ else
+ ret = (xmlParserErrors)ctxt->errNo;
+ } else {
+ ret = XML_ERR_OK;
+ }
+
+ /*
+ * Return the newly created nodeset after unlinking it from
+ * the pseudo sibling.
+ */
+
+ cur = fake->next;
+ fake->next = NULL;
+ node->last = fake;
+
+ if (cur != NULL) {
+ cur->prev = NULL;
+ }
+
+ *lst = cur;
+
+ while (cur != NULL) {
+ cur->parent = NULL;
+ cur = cur->next;
+ }
+
+ xmlUnlinkNode(fake);
+ xmlFreeNode(fake);
+
+
+ if (ret != XML_ERR_OK) {
+ xmlFreeNodeList(*lst);
+ *lst = NULL;
+ }
+
+ if (doc->dict != NULL)
+ ctxt->dict = NULL;
+ xmlFreeParserCtxt(ctxt);
+
+ return(ret);
+#else /* !SAX2 */
+ return(XML_ERR_INTERNAL_ERROR);
+#endif
+}
+
+#ifdef LIBXML_SAX1_ENABLED
+/**
+ * xmlParseBalancedChunkMemoryRecover:
+ * @doc: the document the chunk pertains to
+ * @sax: the SAX handler bloc (possibly NULL)
+ * @user_data: The user data returned on SAX callbacks (possibly NULL)
+ * @depth: Used for loop detection, use 0
+ * @string: the input string in UTF8 or ISO-Latin (zero terminated)
+ * @lst: the return value for the set of parsed nodes
+ * @recover: return nodes even if the data is broken (use 0)
+ *
+ *
+ * Parse a well-balanced chunk of an XML document
+ * called by the parser
+ * The allowed sequence for the Well Balanced Chunk is the one defined by
+ * the content production in the XML grammar:
+ *
+ * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
+ *
+ * Returns 0 if the chunk is well balanced, -1 in case of args problem and
+ * the parser error code otherwise
+ *
+ * In case recover is set to 1, the nodelist will not be empty even if
+ * the parsed chunk is not well balanced.
+ */
+int
+xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
+ void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst,
+ int recover) {
+ xmlParserCtxtPtr ctxt;
+ xmlDocPtr newDoc;
+ xmlSAXHandlerPtr oldsax = NULL;
+ xmlNodePtr content, newRoot;
+ int size;
+ int ret = 0;
+
+ if (depth > 40) {
+ return(XML_ERR_ENTITY_LOOP);
+ }
+
+
+ if (lst != NULL)
+ *lst = NULL;
+ if (string == NULL)
+ return(-1);
+
+ size = xmlStrlen(string);
+
+ ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
+ if (ctxt == NULL) return(-1);
+ ctxt->userData = ctxt;
+ if (sax != NULL) {
+ oldsax = ctxt->sax;
+ ctxt->sax = sax;
+ if (user_data != NULL)
+ ctxt->userData = user_data;
+ }
+ newDoc = xmlNewDoc(BAD_CAST "1.0");
+ if (newDoc == NULL) {
+ xmlFreeParserCtxt(ctxt);
+ return(-1);
+ }
+ if ((doc != NULL) && (doc->dict != NULL)) {
+ xmlDictFree(ctxt->dict);
+ ctxt->dict = doc->dict;
+ xmlDictReference(ctxt->dict);
+ 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);
+ ctxt->dictNames = 1;
+ } else {
+ xmlCtxtUseOptions(ctxt, XML_PARSE_NODICT);
+ }
+ if (doc != NULL) {
+ newDoc->intSubset = doc->intSubset;
+ newDoc->extSubset = doc->extSubset;
+ }
+ newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
+ if (newRoot == NULL) {
+ if (sax != NULL)
+ ctxt->sax = oldsax;
+ xmlFreeParserCtxt(ctxt);
+ newDoc->intSubset = NULL;
+ newDoc->extSubset = NULL;
+ xmlFreeDoc(newDoc);
+ return(-1);
+ }
+ xmlAddChild((xmlNodePtr) newDoc, newRoot);
+ nodePush(ctxt, newRoot);
+ if (doc == NULL) {
+ ctxt->myDoc = newDoc;
+ } else {
+ ctxt->myDoc = newDoc;
+ newDoc->children->doc = doc;
+ /* Ensure that doc has XML spec namespace */
+ xmlSearchNsByHref(doc, (xmlNodePtr)doc, XML_XML_NAMESPACE);
+ newDoc->oldNs = doc->oldNs;
+ }
+ ctxt->instate = XML_PARSER_CONTENT;
+ ctxt->depth = depth;
+
+ /*
+ * Doing validity checking on chunk doesn't make sense
+ */
+ ctxt->validate = 0;
+ ctxt->loadsubset = 0;
+ xmlDetectSAX2(ctxt);
+
+ if ( doc != NULL ){
+ content = doc->children;
+ doc->children = NULL;
+ xmlParseContent(ctxt);
+ doc->children = content;
+ }
+ else {
+ xmlParseContent(ctxt);
+ }
+ if ((RAW == '<') && (NXT(1) == '/')) {
+ xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
+ } else if (RAW != 0) {
+ xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
+ }
+ if (ctxt->node != newDoc->children) {
+ xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
+ }
+
+ if (!ctxt->wellFormed) {
+ if (ctxt->errNo == 0)
+ ret = 1;
+ else
+ ret = ctxt->errNo;
+ } else {
+ ret = 0;
+ }
+
+ if ((lst != NULL) && ((ret == 0) || (recover == 1))) {
+ xmlNodePtr cur;
+
+ /*
+ * Return the newly created nodeset after unlinking it from
+ * they pseudo parent.
+ */
+ cur = newDoc->children->children;
+ *lst = cur;
+ while (cur != NULL) {
+ xmlSetTreeDoc(cur, doc);
+ cur->parent = NULL;
+ cur = cur->next;
+ }
+ newDoc->children->children = NULL;
+ }
+
+ if (sax != NULL)
+ ctxt->sax = oldsax;
+ xmlFreeParserCtxt(ctxt);
+ newDoc->intSubset = NULL;
+ newDoc->extSubset = NULL;
+ newDoc->oldNs = NULL;
+ xmlFreeDoc(newDoc);
+
+ return(ret);
+}
+
+/**
+ * xmlSAXParseEntity:
+ * @sax: the SAX handler block
+ * @filename: the filename
+ *
+ * parse an XML external entity out of context 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.
+ *
+ * [78] extParsedEnt ::= TextDecl? content
+ *
+ * This correspond to a "Well Balanced" chunk
+ *
+ * Returns the resulting document tree
+ */
+
+xmlDocPtr
+xmlSAXParseEntity(xmlSAXHandlerPtr sax, const char *filename) {
+ xmlDocPtr ret;
+ xmlParserCtxtPtr ctxt;
+
+ ctxt = xmlCreateFileParserCtxt(filename);
+ if (ctxt == NULL) {
+ return(NULL);
+ }
+ if (sax != NULL) {
+ if (ctxt->sax != NULL)
+ xmlFree(ctxt->sax);
+ ctxt->sax = sax;
+ ctxt->userData = NULL;
+ }
+
+ xmlParseExtParsedEnt(ctxt);
+
+ if (ctxt->wellFormed)
+ ret = ctxt->myDoc;
+ else {
+ ret = NULL;
+ xmlFreeDoc(ctxt->myDoc);
+ ctxt->myDoc = NULL;
+ }
+ if (sax != NULL)
+ ctxt->sax = NULL;
+ xmlFreeParserCtxt(ctxt);
+
+ return(ret);
+}
+
+/**
+ * xmlParseEntity:
+ * @filename: the filename
+ *
+ * parse an XML external entity out of context and build a tree.
+ *
+ * [78] extParsedEnt ::= TextDecl? content
+ *
+ * This correspond to a "Well Balanced" chunk
+ *
+ * Returns the resulting document tree
+ */
+
+xmlDocPtr
+xmlParseEntity(const char *filename) {
+ return(xmlSAXParseEntity(NULL, filename));
+}
+#endif /* LIBXML_SAX1_ENABLED */
+
+/**
+ * xmlCreateEntityParserCtxt:
+ * @URL: the entity URL
+ * @ID: the entity PUBLIC ID
+ * @base: a possible base for the target URI
+ *
+ * Create a parser context for an external entity
+ * Automatic support for ZLIB/Compress compressed document is provided
+ * by default if found at compile-time.
+ *
+ * Returns the new parser context or NULL
+ */
+xmlParserCtxtPtr
+xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID,
+ const xmlChar *base) {
+ xmlParserCtxtPtr ctxt;
+ xmlParserInputPtr inputStream;
+ char *directory = NULL;
+ xmlChar *uri;
+
+ ctxt = xmlNewParserCtxt();
+ if (ctxt == NULL) {
+ return(NULL);
+ }
+
+ uri = xmlBuildURI(URL, base);
+
+ if (uri == NULL) {
+ inputStream = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt);
+ if (inputStream == NULL) {
+ xmlFreeParserCtxt(ctxt);
+ return(NULL);
+ }
+
+ inputPush(ctxt, inputStream);
+
+ if ((ctxt->directory == NULL) && (directory == NULL))
+ directory = xmlParserGetDirectory((char *)URL);
+ if ((ctxt->directory == NULL) && (directory != NULL))
+ ctxt->directory = directory;
+ } else {
+ inputStream = xmlLoadExternalEntity((char *)uri, (char *)ID, ctxt);
+ if (inputStream == NULL) {
+ xmlFree(uri);
+ xmlFreeParserCtxt(ctxt);
+ return(NULL);
+ }
+
+ inputPush(ctxt, inputStream);
+
+ if ((ctxt->directory == NULL) && (directory == NULL))
+ directory = xmlParserGetDirectory((char *)uri);
+ if ((ctxt->directory == NULL) && (directory != NULL))
+ ctxt->directory = directory;
+ xmlFree(uri);
+ }
+ return(ctxt);
+}
+
+/************************************************************************
+ * *
+ * Front ends when parsing from a file *
+ * *
+ ************************************************************************/
+
+/**
+ * xmlCreateURLParserCtxt:
+ * @filename: the filename or URL
+ * @options: a combination of xmlParserOption
+ *
+ * Create a parser context for a file or URL content.
+ * Automatic support for ZLIB/Compress compressed document is provided
+ * by default if found at compile-time and for file accesses
+ *
+ * Returns the new parser context or NULL
+ */
+xmlParserCtxtPtr
+xmlCreateURLParserCtxt(const char *filename, int options)
+{
+ xmlParserCtxtPtr ctxt;
+ xmlParserInputPtr inputStream;
+ char *directory = NULL;
+
+ ctxt = xmlNewParserCtxt();
+ if (ctxt == NULL) {
+ xmlErrMemory(NULL, "cannot allocate parser context");
+ return(NULL);
+ }
+
+ if (options)
+ xmlCtxtUseOptions(ctxt, options);
+ ctxt->linenumbers = 1;
+
+ inputStream = xmlLoadExternalEntity(filename, NULL, ctxt);
+ if (inputStream == NULL) {
+ xmlFreeParserCtxt(ctxt);
+ return(NULL);
+ }
+
+ inputPush(ctxt, inputStream);
+ if ((ctxt->directory == NULL) && (directory == NULL))
+ directory = xmlParserGetDirectory(filename);
+ if ((ctxt->directory == NULL) && (directory != NULL))
+ ctxt->directory = directory;
+
+ return(ctxt);
+}
+
+/**
+ * xmlCreateFileParserCtxt:
+ * @filename: the filename
+ *
+ * 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
+ */
+xmlParserCtxtPtr
+xmlCreateFileParserCtxt(const char *filename)
+{
+ return(xmlCreateURLParserCtxt(filename, 0));
+}
+
+#ifdef LIBXML_SAX1_ENABLED
+/**
+ * xmlSAXParseFileWithData:
+ * @sax: the SAX handler block
+ * @filename: the filename
+ * @recovery: work in recovery mode, i.e. tries to read no Well Formed
+ * documents
+ * @data: the userdata
+ *
+ * parse an XML 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.
+ *
+ * User data (void *) is stored within the parser context in the
+ * context's _private member, so it is available nearly everywhere in libxml
+ *
+ * Returns the resulting document tree
+ */
+
+xmlDocPtr
+xmlSAXParseFileWithData(xmlSAXHandlerPtr sax, const char *filename,
+ int recovery, void *data) {
+ xmlDocPtr ret;
+ xmlParserCtxtPtr ctxt;
+ char *directory = NULL;
+
+ xmlInitParser();
+
+ ctxt = xmlCreateFileParserCtxt(filename);
+ if (ctxt == NULL) {
+ return(NULL);
+ }
+ if (sax != NULL) {
+ if (ctxt->sax != NULL)
+ xmlFree(ctxt->sax);
+ ctxt->sax = sax;
+ }
+ xmlDetectSAX2(ctxt);
+ if (data!=NULL) {
+ ctxt->_private = data;
+ }
+
+ if ((ctxt->directory == NULL) && (directory == NULL))
+ directory = xmlParserGetDirectory(filename);
+ if ((ctxt->directory == NULL) && (directory != NULL))
+ ctxt->directory = (char *) xmlStrdup((xmlChar *) directory);
+
+ ctxt->recovery = recovery;
+
+ xmlParseDocument(ctxt);
+
+ if ((ctxt->wellFormed) || recovery) {
+ ret = ctxt->myDoc;
+ if (ret != NULL) {
+ if (ctxt->input->buf->compressed > 0)
+ ret->compression = 9;
+ else
+ ret->compression = ctxt->input->buf->compressed;
+ }
+ }
+ else {
+ ret = NULL;
+ xmlFreeDoc(ctxt->myDoc);
+ ctxt->myDoc = NULL;
+ }
+ if (sax != NULL)
+ ctxt->sax = NULL;
+ xmlFreeParserCtxt(ctxt);
+
+ return(ret);
+}
+
+/**
+ * xmlSAXParseFile:
+ * @sax: the SAX handler block
+ * @filename: the filename
+ * @recovery: work in recovery mode, i.e. tries to read no Well Formed
+ * documents
+ *
+ * parse an XML 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
+ */
+
+xmlDocPtr
+xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename,
+ int recovery) {
+ return(xmlSAXParseFileWithData(sax,filename,recovery,NULL));
+}
+
+/**
+ * xmlRecoverDoc:
+ * @cur: a pointer to an array of xmlChar
+ *
+ * parse an XML in-memory document and build a tree.
+ * In the case the document is not Well Formed, a tree is built anyway
+ *
+ * Returns the resulting document tree
+ */
+
+xmlDocPtr
+xmlRecoverDoc(xmlChar *cur) {
+ return(xmlSAXParseDoc(NULL, cur, 1));
+}
+
+/**
+ * xmlParseFile:
+ * @filename: the filename
+ *
+ * parse an XML 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 if the file was wellformed,
+ * NULL otherwise.
+ */
+
+xmlDocPtr
+xmlParseFile(const char *filename) {
+ return(xmlSAXParseFile(NULL, filename, 0));
+}
+
+/**
+ * xmlRecoverFile:
+ * @filename: the filename
+ *
+ * parse an XML file and build a tree. Automatic support for ZLIB/Compress
+ * compressed document is provided by default if found at compile-time.
+ * In the case the document is not Well Formed, a tree is built anyway
+ *
+ * Returns the resulting document tree
+ */
+
+xmlDocPtr
+xmlRecoverFile(const char *filename) {
+ return(xmlSAXParseFile(NULL, filename, 1));
+}
+
+
+/**
+ * xmlSetupParserForBuffer:
+ * @ctxt: an XML parser context
+ * @buffer: a xmlChar * buffer
+ * @filename: a file name
+ *
+ * Setup the parser context to parse a new buffer; Clears any prior
+ * contents from the parser context. The buffer parameter must not be
+ * NULL, but the filename parameter can be
+ */
+void
+xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer,
+ const char* filename)
+{
+ xmlParserInputPtr input;
+
+ if ((ctxt == NULL) || (buffer == NULL))
+ return;
+
+ input = xmlNewInputStream(ctxt);
+ if (input == NULL) {
+ xmlErrMemory(NULL, "parsing new buffer: out of memory\n");
+ xmlClearParserCtxt(ctxt);
+ return;
+ }
+
+ xmlClearParserCtxt(ctxt);
+ if (filename != NULL)
+ input->filename = (char *) xmlCanonicPath((const xmlChar *)filename);
+ input->base = buffer;
+ input->cur = buffer;
+ input->end = &buffer[xmlStrlen(buffer)];
+ inputPush(ctxt, input);
+}
+
+/**
+ * xmlSAXUserParseFile:
+ * @sax: a SAX handler
+ * @user_data: The user data returned on SAX callbacks
+ * @filename: a file name
+ *
+ * parse an XML file and call the given SAX handler routines.
+ * Automatic support for ZLIB/Compress compressed document is provided
+ *
+ * Returns 0 in case of success or a error number otherwise
+ */
+int
+xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data,
+ const char *filename) {
+ int ret = 0;
+ xmlParserCtxtPtr ctxt;
+
+ ctxt = xmlCreateFileParserCtxt(filename);
+ if (ctxt == NULL) return -1;
+#ifdef LIBXML_SAX1_ENABLED
+ if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
+#endif /* LIBXML_SAX1_ENABLED */
+ xmlFree(ctxt->sax);
+ ctxt->sax = sax;
+ xmlDetectSAX2(ctxt);
+
+ if (user_data != NULL)
+ ctxt->userData = user_data;
+
+ xmlParseDocument(ctxt);
+
+ if (ctxt->wellFormed)
+ ret = 0;
+ else {
+ if (ctxt->errNo != 0)
+ ret = ctxt->errNo;
+ else
+ ret = -1;
+ }
+ if (sax != NULL)
+ ctxt->sax = NULL;
+ if (ctxt->myDoc != NULL) {
+ xmlFreeDoc(ctxt->myDoc);
+ ctxt->myDoc = NULL;
+ }
+ xmlFreeParserCtxt(ctxt);
+
+ return ret;
+}
+#endif /* LIBXML_SAX1_ENABLED */
+
+/************************************************************************
+ * *
+ * Front ends when parsing from memory *
+ * *
+ ************************************************************************/
+
+/**
+ * xmlCreateMemoryParserCtxt:
+ * @buffer: a pointer to a char array
+ * @size: the size of the array
+ *
+ * Create a parser context for an XML in-memory document.
+ *
+ * Returns the new parser context or NULL
+ */
+xmlParserCtxtPtr
+xmlCreateMemoryParserCtxt(const char *buffer, int size) {
+ xmlParserCtxtPtr ctxt;
+ xmlParserInputPtr input;
+ xmlParserInputBufferPtr buf;
+
+ if (buffer == NULL)
+ return(NULL);
+ if (size <= 0)
+ return(NULL);
+
+ ctxt = xmlNewParserCtxt();
+ if (ctxt == NULL)
+ return(NULL);
+
+ /* TODO: xmlParserInputBufferCreateStatic, requires some serious changes */
+ buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
+ if (buf == NULL) {
+ xmlFreeParserCtxt(ctxt);
+ return(NULL);
+ }
+
+ input = xmlNewInputStream(ctxt);
+ if (input == NULL) {
+ xmlFreeParserInputBuffer(buf);
+ xmlFreeParserCtxt(ctxt);
+ return(NULL);
+ }
+
+ input->filename = NULL;
+ input->buf = buf;
+ input->base = input->buf->buffer->content;
+ input->cur = input->buf->buffer->content;
+ input->end = &input->buf->buffer->content[input->buf->buffer->use];
+
+ inputPush(ctxt, input);
+ return(ctxt);
+}
+
+#ifdef LIBXML_SAX1_ENABLED
+/**
+ * xmlSAXParseMemoryWithData:
+ * @sax: the SAX handler block
+ * @buffer: an pointer to a char array
+ * @size: the size of the array
+ * @recovery: work in recovery mode, i.e. tries to read no Well Formed
+ * documents
+ * @data: the userdata
+ *
+ * parse an XML in-memory block and use the given SAX function block
+ * to handle the parsing callback. If sax is NULL, fallback to the default
+ * DOM tree building routines.
+ *
+ * User data (void *) is stored within the parser context in the
+ * context's _private member, so it is available nearly everywhere in libxml
+ *
+ * Returns the resulting document tree
+ */
+
+xmlDocPtr
+xmlSAXParseMemoryWithData(xmlSAXHandlerPtr sax, const char *buffer,
+ int size, int recovery, void *data) {
+ xmlDocPtr ret;
+ xmlParserCtxtPtr ctxt;
+
+ ctxt = xmlCreateMemoryParserCtxt(buffer, size);
+ if (ctxt == NULL) return(NULL);
+ if (sax != NULL) {
+ if (ctxt->sax != NULL)
+ xmlFree(ctxt->sax);
+ ctxt->sax = sax;
+ }
+ xmlDetectSAX2(ctxt);
+ if (data!=NULL) {
+ ctxt->_private=data;
+ }
+
+ ctxt->recovery = recovery;
+
+ xmlParseDocument(ctxt);
+
+ if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
+ else {
+ ret = NULL;
+ xmlFreeDoc(ctxt->myDoc);
+ ctxt->myDoc = NULL;
+ }
+ if (sax != NULL)
+ ctxt->sax = NULL;
+ xmlFreeParserCtxt(ctxt);
+
+ return(ret);
+}
+
+/**
+ * xmlSAXParseMemory:
+ * @sax: the SAX handler block
+ * @buffer: an pointer to a char array
+ * @size: the size of the array
+ * @recovery: work in recovery mode, i.e. tries to read not Well Formed
+ * documents
+ *
+ * parse an XML in-memory block and 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
+ */
+xmlDocPtr
+xmlSAXParseMemory(xmlSAXHandlerPtr sax, const char *buffer,
+ int size, int recovery) {
+ return xmlSAXParseMemoryWithData(sax, buffer, size, recovery, NULL);
+}
+
+/**
+ * xmlParseMemory:
+ * @buffer: an pointer to a char array
+ * @size: the size of the array
+ *
+ * parse an XML in-memory block and build a tree.
+ *
+ * Returns the resulting document tree
+ */
+
+xmlDocPtr xmlParseMemory(const char *buffer, int size) {
+ return(xmlSAXParseMemory(NULL, buffer, size, 0));
+}
+
+/**
+ * xmlRecoverMemory:
+ * @buffer: an pointer to a char array
+ * @size: the size of the array
+ *
+ * parse an XML in-memory block and build a tree.
+ * In the case the document is not Well Formed, a tree is built anyway
+ *
+ * Returns the resulting document tree
+ */
+
+xmlDocPtr xmlRecoverMemory(const char *buffer, int size) {
+ return(xmlSAXParseMemory(NULL, buffer, size, 1));
+}
+
+/**
+ * xmlSAXUserParseMemory:
+ * @sax: a SAX handler
+ * @user_data: The user data returned on SAX callbacks
+ * @buffer: an in-memory XML document input
+ * @size: the length of the XML document in bytes
+ *
+ * A better SAX parsing routine.
+ * parse an XML in-memory buffer and call the given SAX handler routines.
+ *
+ * Returns 0 in case of success or a error number otherwise
+ */
+int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data,
+ const char *buffer, int size) {
+ int ret = 0;
+ xmlParserCtxtPtr ctxt;
+ xmlSAXHandlerPtr oldsax = NULL;
+
+ if (sax == NULL) return -1;
+ ctxt = xmlCreateMemoryParserCtxt(buffer, size);
+ if (ctxt == NULL) return -1;
+ oldsax = ctxt->sax;
+ ctxt->sax = sax;
+ xmlDetectSAX2(ctxt);
+ if (user_data != NULL)
+ ctxt->userData = user_data;
+
+ xmlParseDocument(ctxt);
+
+ if (ctxt->wellFormed)
+ ret = 0;
+ else {
+ if (ctxt->errNo != 0)
+ ret = ctxt->errNo;
+ else
+ ret = -1;
+ }
+ ctxt->sax = oldsax;
+ if (ctxt->myDoc != NULL) {
+ xmlFreeDoc(ctxt->myDoc);
+ ctxt->myDoc = NULL;
+ }
+ xmlFreeParserCtxt(ctxt);
+
+ return ret;
+}
+#endif /* LIBXML_SAX1_ENABLED */
+
+/**
+ * xmlCreateDocParserCtxt:
+ * @cur: a pointer to an array of xmlChar
+ *
+ * Creates a parser context for an XML in-memory document.
+ *
+ * Returns the new parser context or NULL
+ */
+xmlParserCtxtPtr
+xmlCreateDocParserCtxt(const xmlChar *cur) {
+ int len;
+
+ if (cur == NULL)
+ return(NULL);
+ len = xmlStrlen(cur);
+ return(xmlCreateMemoryParserCtxt((const char *)cur, len));
+}
+
+#ifdef LIBXML_SAX1_ENABLED
+/**
+ * xmlSAXParseDoc:
+ * @sax: the SAX handler block
+ * @cur: a pointer to an array of xmlChar
+ * @recovery: work in recovery mode, i.e. tries to read no Well Formed
+ * documents
+ *
+ * parse an XML 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
+ */
+
+xmlDocPtr
+xmlSAXParseDoc(xmlSAXHandlerPtr sax, const xmlChar *cur, int recovery) {
+ xmlDocPtr ret;
+ xmlParserCtxtPtr ctxt;
+ xmlSAXHandlerPtr oldsax = NULL;
+
+ if (cur == NULL) return(NULL);
+
+
+ ctxt = xmlCreateDocParserCtxt(cur);
+ if (ctxt == NULL) return(NULL);
+ if (sax != NULL) {
+ oldsax = ctxt->sax;
+ ctxt->sax = sax;
+ ctxt->userData = NULL;
+ }
+ xmlDetectSAX2(ctxt);
+
+ xmlParseDocument(ctxt);
+ if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
+ else {
+ ret = NULL;
+ xmlFreeDoc(ctxt->myDoc);
+ ctxt->myDoc = NULL;
+ }
+ if (sax != NULL)
+ ctxt->sax = oldsax;
+ xmlFreeParserCtxt(ctxt);
+
+ return(ret);
+}
+
+/**
+ * xmlParseDoc:
+ * @cur: a pointer to an array of xmlChar
+ *
+ * parse an XML in-memory document and build a tree.
+ *
+ * Returns the resulting document tree
+ */
+
+xmlDocPtr
+xmlParseDoc(const xmlChar *cur) {
+ return(xmlSAXParseDoc(NULL, cur, 0));
+}
+#endif /* LIBXML_SAX1_ENABLED */
+
+#ifdef LIBXML_LEGACY_ENABLED
+/************************************************************************
+ * *
+ * Specific function to keep track of entities references *
+ * and used by the XSLT debugger *
+ * *
+ ************************************************************************/
+
+static xmlEntityReferenceFunc xmlEntityRefFunc = NULL;
+
+/**
+ * xmlAddEntityReference:
+ * @ent : A valid entity
+ * @firstNode : A valid first node for children of entity
+ * @lastNode : A valid last node of children entity
+ *
+ * Notify of a reference to an entity of type XML_EXTERNAL_GENERAL_PARSED_ENTITY
+ */
+static void
+xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
+ xmlNodePtr lastNode)
+{
+ if (xmlEntityRefFunc != NULL) {
+ (*xmlEntityRefFunc) (ent, firstNode, lastNode);
+ }
+}
+
+
+/**
+ * xmlSetEntityReferenceFunc:
+ * @func: A valid function
+ *
+ * Set the function to call call back when a xml reference has been made
+ */
+void
+xmlSetEntityReferenceFunc(xmlEntityReferenceFunc func)
+{
+ xmlEntityRefFunc = func;
+}
+#endif /* LIBXML_LEGACY_ENABLED */
+
+/************************************************************************
+ * *
+ * Miscellaneous *
+ * *
+ ************************************************************************/
+
+#ifdef LIBXML_XPATH_ENABLED
+#include <libxml/xpath.h>
+#endif
+
+extern void XMLCDECL xmlGenericErrorDefaultFunc(void *ctx, const char *msg, ...);
+static int xmlParserInitialized = 0;
+
+/**
+ * xmlInitParser:
+ *
+ * Initialization function for the XML parser.
+ * This is not reentrant. Call once before processing in case of
+ * use in multithreaded programs.
+ */
+
+void
+xmlInitParser(void) {
+ if (xmlParserInitialized != 0)
+ return;
+
+ if ((xmlGenericError == xmlGenericErrorDefaultFunc) ||
+ (xmlGenericError == NULL))
+ initGenericErrorDefaultFunc(NULL);
+ xmlInitGlobals();
+ xmlInitThreads();
+ xmlInitMemory();
+ xmlInitCharEncodingHandlers();
+ xmlDefaultSAXHandlerInit();
+ xmlRegisterDefaultInputCallbacks();
+#ifdef LIBXML_OUTPUT_ENABLED
+ xmlRegisterDefaultOutputCallbacks();
+#endif /* LIBXML_OUTPUT_ENABLED */
+#ifdef LIBXML_HTML_ENABLED
+ htmlInitAutoClose();
+ htmlDefaultSAXHandlerInit();
+#endif
+#ifdef LIBXML_XPATH_ENABLED
+ xmlXPathInit();
+#endif
+ xmlParserInitialized = 1;
+}
+
+/**
+ * xmlCleanupParser:
+ *
+ * Cleanup function for the XML library. It tries to reclaim all
+ * parsing related global memory allocated for the library processing.
+ * It doesn't deallocate any document related memory. Calling this
+ * function should not prevent reusing the library but one should
+ * call xmlCleanupParser() only when the process has
+ * finished using the library or XML document built with it.
+ */
+
+void
+xmlCleanupParser(void) {
+ if (!xmlParserInitialized)
+ return;
+
+ xmlCleanupCharEncodingHandlers();
+#ifdef LIBXML_CATALOG_ENABLED
+ xmlCatalogCleanup();
+#endif
+ xmlDictCleanup();
+ xmlCleanupInputCallbacks();
+#ifdef LIBXML_OUTPUT_ENABLED
+ xmlCleanupOutputCallbacks();
+#endif
+#ifdef LIBXML_SCHEMAS_ENABLED
+ xmlSchemaCleanupTypes();
+ xmlRelaxNGCleanupTypes();
+#endif
+ xmlCleanupGlobals();
+ xmlResetLastError();
+ xmlCleanupThreads(); /* must be last if called not from the main thread */
+ xmlCleanupMemory();
+ xmlParserInitialized = 0;
+}
+
+/************************************************************************
+ * *
+ * 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));
+
+/**
+ * xmlCtxtReset:
+ * @ctxt: an XML parser context
+ *
+ * Reset a parser context
+ */
+void
+xmlCtxtReset(xmlParserCtxtPtr ctxt)
+{
+ xmlParserInputPtr input;
+ xmlDictPtr dict;
+
+ if (ctxt == NULL)
+ return;
+
+ dict = ctxt->dict;
+
+ while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */
+ xmlFreeInputStream(input);
+ }
+ ctxt->inputNr = 0;
+ ctxt->input = NULL;
+
+ ctxt->spaceNr = 0;
+ ctxt->spaceTab[0] = -1;
+ ctxt->space = &ctxt->spaceTab[0];
+
+
+ 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 = 0;
+ ctxt->external = 0;
+ ctxt->instate = XML_PARSER_START;
+ ctxt->token = 0;
+
+ ctxt->wellFormed = 1;
+ ctxt->nsWellFormed = 1;
+ ctxt->disableSAX = 0;
+ ctxt->valid = 1;
+#if 0
+ ctxt->vctxt.userData = ctxt;
+ ctxt->vctxt.error = xmlParserValidityError;
+ ctxt->vctxt.warning = xmlParserValidityWarning;
+#endif
+ 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;
+ }
+
+#ifdef LIBXML_CATALOG_ENABLED
+ if (ctxt->catalogs != NULL)
+ xmlCatalogFreeLocal(ctxt->catalogs);
+#endif
+ if (ctxt->lastError.code != XML_ERR_OK)
+ xmlResetError(&ctxt->lastError);
+}
+
+/**
+ * xmlCtxtResetPush:
+ * @ctxt: an XML parser context
+ * @chunk: a pointer to an array of chars
+ * @size: number of chars in the array
+ * @filename: an optional file name or URI
+ * @encoding: the document encoding, or NULL
+ *
+ * Reset a push parser context
+ *
+ * Returns 0 in case of success and 1 in case of error
+ */
+int
+xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk,
+ int size, const char *filename, const char *encoding)
+{
+ xmlParserInputPtr inputStream;
+ xmlParserInputBufferPtr buf;
+ xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
+
+ if (ctxt == NULL)
+ return(1);
+
+ if ((encoding == NULL) && (chunk != NULL) && (size >= 4))
+ enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
+
+ buf = xmlAllocParserInputBuffer(enc);
+ if (buf == NULL)
+ return(1);
+
+ if (ctxt == NULL) {
+ xmlFreeParserInputBuffer(buf);
+ return(1);
+ }
+
+ xmlCtxtReset(ctxt);
+
+ if (ctxt->pushTab == NULL) {
+ ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 *
+ sizeof(xmlChar *));
+ if (ctxt->pushTab == NULL) {
+ xmlErrMemory(ctxt, NULL);
+ xmlFreeParserInputBuffer(buf);
+ return(1);
+ }
+ }
+
+ if (filename == NULL) {
+ ctxt->directory = NULL;
+ } else {
+ ctxt->directory = xmlParserGetDirectory(filename);
+ }
+
+ inputStream = xmlNewInputStream(ctxt);
+ if (inputStream == NULL) {
+ xmlFreeParserInputBuffer(buf);
+ return(1);
+ }
+
+ 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, "PP: pushed %d\n", size);
+#endif
+ }
+
+ if (encoding != NULL) {
+ xmlCharEncodingHandlerPtr hdlr;
+
+ hdlr = xmlFindCharEncodingHandler(encoding);
+ if (hdlr != NULL) {
+ xmlSwitchToEncoding(ctxt, hdlr);
+ } else {
+ xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
+ "Unsupported encoding %s\n", BAD_CAST encoding);
+ }
+ } else if (enc != XML_CHAR_ENCODING_NONE) {
+ xmlSwitchEncoding(ctxt, enc);
+ }
+
+ return(0);
+}
+
+/**
+ * xmlCtxtUseOptions:
+ * @ctxt: an XML parser context
+ * @options: a combination of xmlParserOption
+ *
+ * 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
+xmlCtxtUseOptions(xmlParserCtxtPtr ctxt, int options)
+{
+ if (ctxt == NULL)
+ return(-1);
+ if (options & XML_PARSE_RECOVER) {
+ ctxt->recovery = 1;
+ options -= XML_PARSE_RECOVER;
+ } else
+ ctxt->recovery = 0;
+ if (options & XML_PARSE_DTDLOAD) {
+ ctxt->loadsubset = XML_DETECT_IDS;
+ options -= XML_PARSE_DTDLOAD;
+ } else
+ ctxt->loadsubset = 0;
+ if (options & XML_PARSE_DTDATTR) {
+ ctxt->loadsubset |= XML_COMPLETE_ATTRS;
+ options -= XML_PARSE_DTDATTR;
+ }
+ if (options & XML_PARSE_NOENT) {
+ ctxt->replaceEntities = 1;
+ /* ctxt->loadsubset |= XML_DETECT_IDS; */
+ options -= XML_PARSE_NOENT;
+ } else
+ ctxt->replaceEntities = 0;
+ if (options & XML_PARSE_PEDANTIC) {
+ ctxt->pedantic = 1;
+ options -= XML_PARSE_PEDANTIC;
+ } else
+ ctxt->pedantic = 0;
+ if (options & XML_PARSE_NOBLANKS) {
+ ctxt->keepBlanks = 0;
+ ctxt->sax->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
+ options -= XML_PARSE_NOBLANKS;
+ } else
+ ctxt->keepBlanks = 1;
+ if (options & XML_PARSE_DTDVALID) {
+ ctxt->validate = 1;
+ if (options & XML_PARSE_NOWARNING)
+ ctxt->vctxt.warning = NULL;
+ if (options & XML_PARSE_NOERROR)
+ ctxt->vctxt.error = NULL;
+ options -= XML_PARSE_DTDVALID;
+ } else
+ ctxt->validate = 0;
+ if (options & XML_PARSE_NOWARNING) {
+ ctxt->sax->warning = NULL;
+ options -= XML_PARSE_NOWARNING;
+ }
+ if (options & XML_PARSE_NOERROR) {
+ ctxt->sax->error = NULL;
+ ctxt->sax->fatalError = NULL;
+ options -= XML_PARSE_NOERROR;
+ }
+#ifdef LIBXML_SAX1_ENABLED
+ if (options & XML_PARSE_SAX1) {
+ ctxt->sax->startElement = xmlSAX2StartElement;
+ ctxt->sax->endElement = xmlSAX2EndElement;
+ ctxt->sax->startElementNs = NULL;
+ ctxt->sax->endElementNs = NULL;
+ ctxt->sax->initialized = 1;
+ options -= XML_PARSE_SAX1;
+ }
+#endif /* LIBXML_SAX1_ENABLED */
+ if (options & XML_PARSE_NODICT) {
+ ctxt->dictNames = 0;
+ options -= XML_PARSE_NODICT;
+ } else {
+ ctxt->dictNames = 1;
+ }
+ if (options & XML_PARSE_NOCDATA) {
+ ctxt->sax->cdataBlock = NULL;
+ options -= XML_PARSE_NOCDATA;
+ }
+ if (options & XML_PARSE_NSCLEAN) {
+ ctxt->options |= XML_PARSE_NSCLEAN;
+ options -= XML_PARSE_NSCLEAN;
+ }
+ if (options & XML_PARSE_NONET) {
+ ctxt->options |= XML_PARSE_NONET;
+ options -= XML_PARSE_NONET;
+ }
+ if (options & XML_PARSE_COMPACT) {
+ ctxt->options |= XML_PARSE_COMPACT;
+ options -= XML_PARSE_COMPACT;
+ }
+ ctxt->linenumbers = 1;
+ return (options);
+}
+
+/**
+ * xmlDoRead:
+ * @ctxt: an XML parser context
+ * @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
+ *
+ * Common front-end for the xmlRead functions
+ *
+ * Returns the resulting document tree or NULL
+ */
+static xmlDocPtr
+xmlDoRead(xmlParserCtxtPtr ctxt, const char *URL, const char *encoding,
+ int options, int reuse)
+{
+ xmlDocPtr ret;
+
+ xmlCtxtUseOptions(ctxt, options);
+ 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);
+ xmlParseDocument(ctxt);
+ if ((ctxt->wellFormed) || ctxt->recovery)
+ ret = ctxt->myDoc;
+ else {
+ ret = NULL;
+ if (ctxt->myDoc != NULL) {
+ xmlFreeDoc(ctxt->myDoc);
+ }
+ }
+ ctxt->myDoc = NULL;
+ if (!reuse) {
+ xmlFreeParserCtxt(ctxt);
+ }
+
+ return (ret);
+}
+
+/**
+ * xmlReadDoc:
+ * @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
+ *
+ * parse an XML in-memory document and build a tree.
+ *
+ * Returns the resulting document tree
+ */
+xmlDocPtr
+xmlReadDoc(const xmlChar * cur, const char *URL, const char *encoding, int options)
+{
+ xmlParserCtxtPtr ctxt;
+
+ if (cur == NULL)
+ return (NULL);
+
+ ctxt = xmlCreateDocParserCtxt(cur);
+ if (ctxt == NULL)
+ return (NULL);
+ return (xmlDoRead(ctxt, URL, encoding, options, 0));
+}
+
+/**
+ * xmlReadFile:
+ * @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.
+ *
+ * Returns the resulting document tree
+ */
+xmlDocPtr
+xmlReadFile(const char *filename, const char *encoding, int options)
+{
+ xmlParserCtxtPtr ctxt;
+
+ ctxt = xmlCreateURLParserCtxt(filename, options);
+ if (ctxt == NULL)
+ return (NULL);
+ return (xmlDoRead(ctxt, NULL, encoding, options, 0));
+}
+
+/**
+ * xmlReadMemory:
+ * @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
+ *
+ * parse an XML in-memory document and build a tree.
+ *
+ * Returns the resulting document tree
+ */
+xmlDocPtr
+xmlReadMemory(const char *buffer, int size, const char *URL, const char *encoding, int options)
+{
+ xmlParserCtxtPtr ctxt;
+
+ ctxt = xmlCreateMemoryParserCtxt(buffer, size);
+ if (ctxt == NULL)
+ return (NULL);
+ return (xmlDoRead(ctxt, URL, encoding, options, 0));
+}
+
+/**
+ * xmlReadFd:
+ * @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
+ *
+ * parse an XML from a file descriptor and build a tree.
+ * NOTE that the file descriptor will not be closed when the
+ * reader is closed or reset.
+ *
+ * Returns the resulting document tree
+ */
+xmlDocPtr
+xmlReadFd(int fd, const char *URL, const char *encoding, int options)
+{
+ xmlParserCtxtPtr ctxt;
+ xmlParserInputBufferPtr input;
+ xmlParserInputPtr stream;
+
+ if (fd < 0)
+ return (NULL);
+
+ input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
+ if (input == NULL)
+ return (NULL);
+ input->closecallback = 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 (xmlDoRead(ctxt, URL, encoding, options, 0));
+}
+
+/**
+ * xmlReadIO:
+ * @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
+ *
+ * parse an XML document from I/O functions and source and build a tree.
+ *
+ * Returns the resulting document tree
+ */
+xmlDocPtr
+xmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
+ void *ioctx, const char *URL, const char *encoding, int options)
+{
+ xmlParserCtxtPtr ctxt;
+ xmlParserInputBufferPtr input;
+ xmlParserInputPtr stream;
+
+ if (ioread == NULL)
+ return (NULL);
+
+ input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
+ 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 (xmlDoRead(ctxt, URL, encoding, options, 0));
+}
+
+/**
+ * xmlCtxtReadDoc:
+ * @ctxt: an XML 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 xmlParserOption
+ *
+ * parse an XML in-memory document and build a tree.
+ * This reuses the existing @ctxt parser context
+ *
+ * Returns the resulting document tree
+ */
+xmlDocPtr
+xmlCtxtReadDoc(xmlParserCtxtPtr ctxt, const xmlChar * cur,
+ const char *URL, const char *encoding, int options)
+{
+ xmlParserInputPtr stream;
+
+ if (cur == NULL)
+ return (NULL);
+ if (ctxt == NULL)
+ return (NULL);
+
+ xmlCtxtReset(ctxt);
+
+ stream = xmlNewStringInputStream(ctxt, cur);
+ if (stream == NULL) {
+ return (NULL);
+ }
+ inputPush(ctxt, stream);
+ return (xmlDoRead(ctxt, URL, encoding, options, 1));
+}
+
+/**
+ * xmlCtxtReadFile:
+ * @ctxt: an XML parser context
+ * @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.
+ * This reuses the existing @ctxt parser context
+ *
+ * Returns the resulting document tree
+ */
+xmlDocPtr
+xmlCtxtReadFile(xmlParserCtxtPtr ctxt, const char *filename,
+ const char *encoding, int options)
+{
+ xmlParserInputPtr stream;
+
+ if (filename == NULL)
+ return (NULL);
+ if (ctxt == NULL)
+ return (NULL);
+
+ xmlCtxtReset(ctxt);
+
+ stream = xmlLoadExternalEntity(filename, NULL, ctxt);
+ if (stream == NULL) {
+ return (NULL);
+ }
+ inputPush(ctxt, stream);
+ return (xmlDoRead(ctxt, NULL, encoding, options, 1));
+}
+
+/**
+ * xmlCtxtReadMemory:
+ * @ctxt: an XML 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 xmlParserOption
+ *
+ * parse an XML in-memory document and build a tree.
+ * This reuses the existing @ctxt parser context
+ *
+ * Returns the resulting document tree
+ */
+xmlDocPtr
+xmlCtxtReadMemory(xmlParserCtxtPtr 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);
+
+ xmlCtxtReset(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 (xmlDoRead(ctxt, URL, encoding, options, 1));
+}
+
+/**
+ * xmlCtxtReadFd:
+ * @ctxt: an XML 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 xmlParserOption
+ *
+ * parse an XML from a file descriptor and build a tree.
+ * This reuses the existing @ctxt parser context
+ * NOTE that the file descriptor will not be closed when the
+ * reader is closed or reset.
+ *
+ * Returns the resulting document tree
+ */
+xmlDocPtr
+xmlCtxtReadFd(xmlParserCtxtPtr 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);
+
+ xmlCtxtReset(ctxt);
+
+
+ input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
+ if (input == NULL)
+ return (NULL);
+ input->closecallback = NULL;
+ stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
+ if (stream == NULL) {
+ xmlFreeParserInputBuffer(input);
+ return (NULL);
+ }
+ inputPush(ctxt, stream);
+ return (xmlDoRead(ctxt, URL, encoding, options, 1));
+}
+
+/**
+ * xmlCtxtReadIO:
+ * @ctxt: an XML 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 xmlParserOption
+ *
+ * parse an XML document from I/O functions and source and build a tree.
+ * This reuses the existing @ctxt parser context
+ *
+ * Returns the resulting document tree
+ */
+xmlDocPtr
+xmlCtxtReadIO(xmlParserCtxtPtr 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);
+
+ xmlCtxtReset(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 (xmlDoRead(ctxt, URL, encoding, options, 1));
+}
+
+#define bottom_parser
+#include "elfgcchack.h"
diff --git a/gettext-tools/gnulib-lib/libxml/parser.in.h b/gettext-tools/gnulib-lib/libxml/parser.in.h
new file mode 100644
index 0000000..31528c4
--- /dev/null
+++ b/gettext-tools/gnulib-lib/libxml/parser.in.h
@@ -0,0 +1,1220 @@
+/*
+ * Summary: the core parser module
+ * Description: Interfaces, constants and types related to the XML parser
+ *
+ * Copy: See Copyright for the status of this software.
+ *
+ * Author: Daniel Veillard
+ */
+
+#ifndef __XML_PARSER_H__
+#define __XML_PARSER_H__
+
+#include <stdarg.h>
+
+#include <libxml/xmlversion.h>
+#include <libxml/tree.h>
+#include <libxml/dict.h>
+#include <libxml/hash.h>
+#include <libxml/valid.h>
+#include <libxml/entities.h>
+#include <libxml/xmlerror.h>
+#include <libxml/xmlstring.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * XML_DEFAULT_VERSION:
+ *
+ * The default version of XML used: 1.0
+ */
+#define XML_DEFAULT_VERSION "1.0"
+
+/**
+ * xmlParserInput:
+ *
+ * An xmlParserInput is an input flow for the XML processor.
+ * Each entity parsed is associated an xmlParserInput (except the
+ * few predefined ones). This is the case both for internal entities
+ * - in which case the flow is already completely in memory - or
+ * external entities - in which case we use the buf structure for
+ * progressive reading and I18N conversions to the internal UTF-8 format.
+ */
+
+/**
+ * xmlParserInputDeallocate:
+ * @str: the string to deallocate
+ *
+ * Callback for freeing some parser input allocations.
+ */
+typedef void (* xmlParserInputDeallocate)(xmlChar *str);
+
+struct _xmlParserInput {
+ /* Input buffer */
+ xmlParserInputBufferPtr buf; /* UTF-8 encoded buffer */
+
+ const char *filename; /* The file analyzed, if any */
+ const char *directory; /* the directory/base of the file */
+ const xmlChar *base; /* Base of the array to parse */
+ const xmlChar *cur; /* Current char being parsed */
+ const xmlChar *end; /* end of the array to parse */
+ int length; /* length if known */
+ int line; /* Current line */
+ int col; /* Current column */
+ /*
+ * NOTE: consumed is only tested for equality in the parser code,
+ * so even if there is an overflow this should not give troubles
+ * for parsing very large instances.
+ */
+ unsigned long consumed; /* How many xmlChars already consumed */
+ xmlParserInputDeallocate free; /* function to deallocate the base */
+ const xmlChar *encoding; /* the encoding string for entity */
+ const xmlChar *version; /* the version string for entity */
+ int standalone; /* Was that entity marked standalone */
+ int id; /* an unique identifier for the entity */
+};
+
+/**
+ * xmlParserNodeInfo:
+ *
+ * The parser can be asked to collect Node informations, i.e. at what
+ * place in the file they were detected.
+ * NOTE: This is off by default and not very well tested.
+ */
+typedef struct _xmlParserNodeInfo xmlParserNodeInfo;
+typedef xmlParserNodeInfo *xmlParserNodeInfoPtr;
+
+struct _xmlParserNodeInfo {
+ const struct _xmlNode* node;
+ /* Position & line # that text that created the node begins & ends on */
+ unsigned long begin_pos;
+ unsigned long begin_line;
+ unsigned long end_pos;
+ unsigned long end_line;
+};
+
+typedef struct _xmlParserNodeInfoSeq xmlParserNodeInfoSeq;
+typedef xmlParserNodeInfoSeq *xmlParserNodeInfoSeqPtr;
+struct _xmlParserNodeInfoSeq {
+ unsigned long maximum;
+ unsigned long length;
+ xmlParserNodeInfo* buffer;
+};
+
+/**
+ * xmlParserInputState:
+ *
+ * The parser is now working also as a state based parser.
+ * The recursive one use the state info for entities processing.
+ */
+typedef enum {
+ XML_PARSER_EOF = -1, /* nothing is to be parsed */
+ XML_PARSER_START = 0, /* nothing has been parsed */
+ XML_PARSER_MISC, /* Misc* before int subset */
+ XML_PARSER_PI, /* Within a processing instruction */
+ XML_PARSER_DTD, /* within some DTD content */
+ XML_PARSER_PROLOG, /* Misc* after internal subset */
+ XML_PARSER_COMMENT, /* within a comment */
+ XML_PARSER_START_TAG, /* within a start tag */
+ XML_PARSER_CONTENT, /* within the content */
+ XML_PARSER_CDATA_SECTION, /* within a CDATA section */
+ XML_PARSER_END_TAG, /* within a closing tag */
+ XML_PARSER_ENTITY_DECL, /* within an entity declaration */
+ XML_PARSER_ENTITY_VALUE, /* within an entity value in a decl */
+ XML_PARSER_ATTRIBUTE_VALUE, /* within an attribute value */
+ XML_PARSER_SYSTEM_LITERAL, /* within a SYSTEM value */
+ XML_PARSER_EPILOG, /* the Misc* after the last end tag */
+ XML_PARSER_IGNORE, /* within an IGNORED section */
+ XML_PARSER_PUBLIC_LITERAL /* within a PUBLIC value */
+} xmlParserInputState;
+
+/**
+ * XML_DETECT_IDS:
+ *
+ * Bit in the loadsubset context field to tell to do ID/REFs lookups.
+ * Use it to initialize xmlLoadExtDtdDefaultValue.
+ */
+#define XML_DETECT_IDS 2
+
+/**
+ * XML_COMPLETE_ATTRS:
+ *
+ * Bit in the loadsubset context field to tell to do complete the
+ * elements attributes lists with the ones defaulted from the DTDs.
+ * Use it to initialize xmlLoadExtDtdDefaultValue.
+ */
+#define XML_COMPLETE_ATTRS 4
+
+/**
+ * XML_SKIP_IDS:
+ *
+ * Bit in the loadsubset context field to tell to not do ID/REFs registration.
+ * Used to initialize xmlLoadExtDtdDefaultValue in some special cases.
+ */
+#define XML_SKIP_IDS 8
+
+/**
+ * xmlParserMode:
+ *
+ * A parser can operate in various modes
+ */
+typedef enum {
+ XML_PARSE_UNKNOWN = 0,
+ XML_PARSE_DOM = 1,
+ XML_PARSE_SAX = 2,
+ XML_PARSE_PUSH_DOM = 3,
+ XML_PARSE_PUSH_SAX = 4,
+ XML_PARSE_READER = 5
+} xmlParserMode;
+
+/**
+ * xmlParserCtxt:
+ *
+ * The parser context.
+ * NOTE This doesn't completely define the parser state, the (current ?)
+ * design of the parser uses recursive function calls since this allow
+ * and easy mapping from the production rules of the specification
+ * to the actual code. The drawback is that the actual function call
+ * also reflect the parser state. However most of the parsing routines
+ * takes as the only argument the parser context pointer, so migrating
+ * to a state based parser for progressive parsing shouldn't be too hard.
+ */
+struct _xmlParserCtxt {
+ struct _xmlSAXHandler *sax; /* The SAX handler */
+ void *userData; /* For SAX interface only, used by DOM build */
+ xmlDocPtr myDoc; /* the document being built */
+ int wellFormed; /* is the document well formed */
+ int replaceEntities; /* shall we replace entities ? */
+ const xmlChar *version; /* the XML version string */
+ const xmlChar *encoding; /* the declared encoding, if any */
+ int standalone; /* standalone document */
+ int html; /* an HTML(1)/Docbook(2) document */
+
+ /* Input stream stack */
+ xmlParserInputPtr input; /* Current input stream */
+ int inputNr; /* Number of current input streams */
+ int inputMax; /* Max number of input streams */
+ xmlParserInputPtr *inputTab; /* stack of inputs */
+
+ /* Node analysis stack only used for DOM building */
+ 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 */
+
+ int record_info; /* Whether node info should be kept */
+ xmlParserNodeInfoSeq node_seq; /* info about each node parsed */
+
+ int errNo; /* error code */
+
+ int hasExternalSubset; /* reference and external subset */
+ int hasPErefs; /* the internal subset has PE refs */
+ int external; /* are we parsing an external entity */
+
+ int valid; /* is the document valid */
+ int validate; /* shall we try to validate ? */
+ xmlValidCtxt vctxt; /* The validity context */
+
+ xmlParserInputState instate; /* current type of input */
+ int token; /* next char look-ahead */
+
+ char *directory; /* the data directory */
+
+ /* Node name stack */
+ const xmlChar *name; /* Current parsed Node */
+ int nameNr; /* Depth of the parsing stack */
+ int nameMax; /* Max depth of the parsing stack */
+ const xmlChar * *nameTab; /* array of nodes */
+
+ long nbChars; /* number of xmlChar processed */
+ long checkIndex; /* used by progressive parsing lookup */
+ int keepBlanks; /* ugly but ... */
+ int disableSAX; /* SAX callbacks are disabled */
+ int inSubset; /* Parsing is in int 1/ext 2 subset */
+ const xmlChar * intSubName; /* name of subset */
+ xmlChar * extSubURI; /* URI of external subset */
+ xmlChar * extSubSystem; /* SYSTEM ID of external subset */
+
+ /* xml:space values */
+ int * space; /* Should the parser preserve spaces */
+ int spaceNr; /* Depth of the parsing stack */
+ int spaceMax; /* Max depth of the parsing stack */
+ int * spaceTab; /* array of space infos */
+
+ int depth; /* to prevent entity substitution loops */
+ xmlParserInputPtr entity; /* used to check entities boundaries */
+ int charset; /* encoding of the in-memory content
+ actually an xmlCharEncoding */
+ int nodelen; /* Those two fields are there to */
+ int nodemem; /* Speed up large node parsing */
+ int pedantic; /* signal pedantic warnings */
+ void *_private; /* For user data, libxml won't touch it */
+
+ int loadsubset; /* should the external subset be loaded */
+ int linenumbers; /* set line number in element content */
+ void *catalogs; /* document's own catalog */
+ int recovery; /* run in recovery mode */
+ int progressive; /* is this a progressive parsing */
+ xmlDictPtr dict; /* dictionnary for the parser */
+ const xmlChar * *atts; /* array for the attributes callbacks */
+ int maxatts; /* the size of the array */
+ int docdict; /* use strings from dict to build tree */
+
+ /*
+ * pre-interned strings
+ */
+ const xmlChar *str_xml;
+ const xmlChar *str_xmlns;
+ const xmlChar *str_xml_ns;
+
+ /*
+ * Everything below is used only by the new SAX mode
+ */
+ int sax2; /* operating in the new SAX mode */
+ int nsNr; /* the number of inherited namespaces */
+ int nsMax; /* the size of the arrays */
+ const xmlChar * *nsTab; /* the array of prefix/namespace name */
+ int *attallocs; /* which attribute were allocated */
+ void * *pushTab; /* array of data for push */
+ xmlHashTablePtr attsDefault; /* defaulted attributes if any */
+ xmlHashTablePtr attsSpecial; /* non-CDATA attributes if any */
+ int nsWellFormed; /* is the document XML Nanespace okay */
+ int options; /* Extra options */
+
+ /*
+ * Those fields are needed only for treaming parsing so far
+ */
+ int dictNames; /* Use dictionary names for the tree */
+ int freeElemsNr; /* number of freed element nodes */
+ xmlNodePtr freeElems; /* List of freed element nodes */
+ int freeAttrsNr; /* number of freed attributes nodes */
+ xmlAttrPtr freeAttrs; /* List of freed attributes nodes */
+
+ /*
+ * the complete error informations for the last error.
+ */
+ xmlError lastError;
+ xmlParserMode parseMode; /* the parser mode */
+};
+
+/**
+ * xmlSAXLocator:
+ *
+ * A SAX Locator.
+ */
+struct _xmlSAXLocator {
+ const xmlChar *(*getPublicId)(void *ctx);
+ const xmlChar *(*getSystemId)(void *ctx);
+ int (*getLineNumber)(void *ctx);
+ int (*getColumnNumber)(void *ctx);
+};
+
+/**
+ * xmlSAXHandler:
+ *
+ * A SAX handler is bunch of callbacks called by the parser when processing
+ * of the input generate data or structure informations.
+ */
+
+/**
+ * resolveEntitySAXFunc:
+ * @ctx: the user data (XML parser context)
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ *
+ * Callback:
+ * The entity loader, to control the loading of external entities,
+ * the application can either:
+ * - override this resolveEntity() callback in the SAX block
+ * - or better use the xmlSetExternalEntityLoader() function to
+ * set up it's own entity resolution routine
+ *
+ * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
+ */
+typedef xmlParserInputPtr (*resolveEntitySAXFunc) (void *ctx,
+ const xmlChar *publicId,
+ const xmlChar *systemId);
+/**
+ * internalSubsetSAXFunc:
+ * @ctx: the user data (XML parser context)
+ * @name: the root element name
+ * @ExternalID: the external ID
+ * @SystemID: the SYSTEM ID (e.g. filename or URL)
+ *
+ * Callback on internal subset declaration.
+ */
+typedef void (*internalSubsetSAXFunc) (void *ctx,
+ const xmlChar *name,
+ const xmlChar *ExternalID,
+ const xmlChar *SystemID);
+/**
+ * externalSubsetSAXFunc:
+ * @ctx: the user data (XML parser context)
+ * @name: the root element name
+ * @ExternalID: the external ID
+ * @SystemID: the SYSTEM ID (e.g. filename or URL)
+ *
+ * Callback on external subset declaration.
+ */
+typedef void (*externalSubsetSAXFunc) (void *ctx,
+ const xmlChar *name,
+ const xmlChar *ExternalID,
+ const xmlChar *SystemID);
+/**
+ * getEntitySAXFunc:
+ * @ctx: the user data (XML parser context)
+ * @name: The entity name
+ *
+ * Get an entity by name.
+ *
+ * Returns the xmlEntityPtr if found.
+ */
+typedef xmlEntityPtr (*getEntitySAXFunc) (void *ctx,
+ const xmlChar *name);
+/**
+ * getParameterEntitySAXFunc:
+ * @ctx: the user data (XML parser context)
+ * @name: The entity name
+ *
+ * Get a parameter entity by name.
+ *
+ * Returns the xmlEntityPtr if found.
+ */
+typedef xmlEntityPtr (*getParameterEntitySAXFunc) (void *ctx,
+ const xmlChar *name);
+/**
+ * entityDeclSAXFunc:
+ * @ctx: the user data (XML parser context)
+ * @name: the entity name
+ * @type: the entity type
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ * @content: the entity value (without processing).
+ *
+ * An entity definition has been parsed.
+ */
+typedef void (*entityDeclSAXFunc) (void *ctx,
+ const xmlChar *name,
+ int type,
+ const xmlChar *publicId,
+ const xmlChar *systemId,
+ xmlChar *content);
+/**
+ * notationDeclSAXFunc:
+ * @ctx: the user data (XML parser context)
+ * @name: The name of the notation
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ *
+ * What to do when a notation declaration has been parsed.
+ */
+typedef void (*notationDeclSAXFunc)(void *ctx,
+ const xmlChar *name,
+ const xmlChar *publicId,
+ const xmlChar *systemId);
+/**
+ * attributeDeclSAXFunc:
+ * @ctx: the user data (XML parser context)
+ * @elem: the name of the element
+ * @fullname: the attribute name
+ * @type: the attribute type
+ * @def: the type of default value
+ * @defaultValue: the attribute default value
+ * @tree: the tree of enumerated value set
+ *
+ * An attribute definition has been parsed.
+ */
+typedef void (*attributeDeclSAXFunc)(void *ctx,
+ const xmlChar *elem,
+ const xmlChar *fullname,
+ int type,
+ int def,
+ const xmlChar *defaultValue,
+ xmlEnumerationPtr tree);
+/**
+ * elementDeclSAXFunc:
+ * @ctx: the user data (XML parser context)
+ * @name: the element name
+ * @type: the element type
+ * @content: the element value tree
+ *
+ * An element definition has been parsed.
+ */
+typedef void (*elementDeclSAXFunc)(void *ctx,
+ const xmlChar *name,
+ int type,
+ xmlElementContentPtr content);
+/**
+ * unparsedEntityDeclSAXFunc:
+ * @ctx: the user data (XML parser context)
+ * @name: The name of the entity
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ * @notationName: the name of the notation
+ *
+ * What to do when an unparsed entity declaration is parsed.
+ */
+typedef void (*unparsedEntityDeclSAXFunc)(void *ctx,
+ const xmlChar *name,
+ const xmlChar *publicId,
+ const xmlChar *systemId,
+ const xmlChar *notationName);
+/**
+ * setDocumentLocatorSAXFunc:
+ * @ctx: the user data (XML parser context)
+ * @loc: A SAX Locator
+ *
+ * Receive the document locator at startup, actually xmlDefaultSAXLocator.
+ * Everything is available on the context, so this is useless in our case.
+ */
+typedef void (*setDocumentLocatorSAXFunc) (void *ctx,
+ xmlSAXLocatorPtr loc);
+/**
+ * startDocumentSAXFunc:
+ * @ctx: the user data (XML parser context)
+ *
+ * Called when the document start being processed.
+ */
+typedef void (*startDocumentSAXFunc) (void *ctx);
+/**
+ * endDocumentSAXFunc:
+ * @ctx: the user data (XML parser context)
+ *
+ * Called when the document end has been detected.
+ */
+typedef void (*endDocumentSAXFunc) (void *ctx);
+/**
+ * startElementSAXFunc:
+ * @ctx: the user data (XML parser context)
+ * @name: The element name, including namespace prefix
+ * @atts: An array of name/value attributes pairs, NULL terminated
+ *
+ * Called when an opening tag has been processed.
+ */
+typedef void (*startElementSAXFunc) (void *ctx,
+ const xmlChar *name,
+ const xmlChar **atts);
+/**
+ * endElementSAXFunc:
+ * @ctx: the user data (XML parser context)
+ * @name: The element name
+ *
+ * Called when the end of an element has been detected.
+ */
+typedef void (*endElementSAXFunc) (void *ctx,
+ const xmlChar *name);
+/**
+ * attributeSAXFunc:
+ * @ctx: the user data (XML parser context)
+ * @name: The attribute name, including namespace prefix
+ * @value: 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.
+ */
+typedef void (*attributeSAXFunc) (void *ctx,
+ const xmlChar *name,
+ const xmlChar *value);
+/**
+ * referenceSAXFunc:
+ * @ctx: the user data (XML parser context)
+ * @name: The entity name
+ *
+ * Called when an entity reference is detected.
+ */
+typedef void (*referenceSAXFunc) (void *ctx,
+ const xmlChar *name);
+/**
+ * charactersSAXFunc:
+ * @ctx: the user data (XML parser context)
+ * @ch: a xmlChar string
+ * @len: the number of xmlChar
+ *
+ * Receiving some chars from the parser.
+ */
+typedef void (*charactersSAXFunc) (void *ctx,
+ const xmlChar *ch,
+ int len);
+/**
+ * ignorableWhitespaceSAXFunc:
+ * @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 characters.
+ */
+typedef void (*ignorableWhitespaceSAXFunc) (void *ctx,
+ const xmlChar *ch,
+ int len);
+/**
+ * processingInstructionSAXFunc:
+ * @ctx: the user data (XML parser context)
+ * @target: the target name
+ * @data: the PI data's
+ *
+ * A processing instruction has been parsed.
+ */
+typedef void (*processingInstructionSAXFunc) (void *ctx,
+ const xmlChar *target,
+ const xmlChar *data);
+/**
+ * commentSAXFunc:
+ * @ctx: the user data (XML parser context)
+ * @value: the comment content
+ *
+ * A comment has been parsed.
+ */
+typedef void (*commentSAXFunc) (void *ctx,
+ const xmlChar *value);
+/**
+ * cdataBlockSAXFunc:
+ * @ctx: the user data (XML parser context)
+ * @value: The pcdata content
+ * @len: the block length
+ *
+ * Called when a pcdata block has been parsed.
+ */
+typedef void (*cdataBlockSAXFunc) (
+ void *ctx,
+ const xmlChar *value,
+ int len);
+/**
+ * warningSAXFunc:
+ * @ctx: an XML parser context
+ * @msg: the message to display/transmit
+ * @...: extra parameters for the message display
+ *
+ * Display and format a warning messages, callback.
+ */
+typedef void (XMLCDECL *warningSAXFunc) (void *ctx,
+ const char *msg, ...);
+/**
+ * errorSAXFunc:
+ * @ctx: an XML parser context
+ * @msg: the message to display/transmit
+ * @...: extra parameters for the message display
+ *
+ * Display and format an error messages, callback.
+ */
+typedef void (XMLCDECL *errorSAXFunc) (void *ctx,
+ const char *msg, ...);
+/**
+ * fatalErrorSAXFunc:
+ * @ctx: an XML parser context
+ * @msg: the message to display/transmit
+ * @...: extra parameters for the message display
+ *
+ * Display and format fatal error messages, callback.
+ * Note: so far fatalError() SAX callbacks are not used, error()
+ * get all the callbacks for errors.
+ */
+typedef void (XMLCDECL *fatalErrorSAXFunc) (void *ctx,
+ const char *msg, ...);
+/**
+ * isStandaloneSAXFunc:
+ * @ctx: the user data (XML parser context)
+ *
+ * Is this document tagged standalone?
+ *
+ * Returns 1 if true
+ */
+typedef int (*isStandaloneSAXFunc) (void *ctx);
+/**
+ * hasInternalSubsetSAXFunc:
+ * @ctx: the user data (XML parser context)
+ *
+ * Does this document has an internal subset.
+ *
+ * Returns 1 if true
+ */
+typedef int (*hasInternalSubsetSAXFunc) (void *ctx);
+
+/**
+ * hasExternalSubsetSAXFunc:
+ * @ctx: the user data (XML parser context)
+ *
+ * Does this document has an external subset?
+ *
+ * Returns 1 if true
+ */
+typedef int (*hasExternalSubsetSAXFunc) (void *ctx);
+
+/************************************************************************
+ * *
+ * The SAX version 3 API extensions *
+ * *
+ ************************************************************************/
+/**
+ * XML_SAX2_MAGIC:
+ *
+ * Special constant found in SAX2 blocks initialized fields
+ */
+#define XML_SAX2_MAGIC 0xDEEDBEAF
+
+/**
+ * startElementNsSAX2Func:
+ * @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. The defaulted
+ * ones are at the end of the array
+ * @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.
+ */
+
+typedef void (*startElementNsSAX2Func) (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);
+
+/**
+ * endElementNsSAX2Func:
+ * @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.
+ */
+
+typedef void (*endElementNsSAX2Func) (void *ctx,
+ const xmlChar *localname,
+ const xmlChar *prefix,
+ const xmlChar *URI);
+
+
+struct _xmlSAXHandler {
+ internalSubsetSAXFunc internalSubset;
+ isStandaloneSAXFunc isStandalone;
+ hasInternalSubsetSAXFunc hasInternalSubset;
+ hasExternalSubsetSAXFunc hasExternalSubset;
+ resolveEntitySAXFunc resolveEntity;
+ getEntitySAXFunc getEntity;
+ entityDeclSAXFunc entityDecl;
+ notationDeclSAXFunc notationDecl;
+ attributeDeclSAXFunc attributeDecl;
+ elementDeclSAXFunc elementDecl;
+ unparsedEntityDeclSAXFunc unparsedEntityDecl;
+ setDocumentLocatorSAXFunc setDocumentLocator;
+ startDocumentSAXFunc startDocument;
+ endDocumentSAXFunc endDocument;
+ startElementSAXFunc startElement;
+ endElementSAXFunc endElement;
+ referenceSAXFunc reference;
+ charactersSAXFunc characters;
+ ignorableWhitespaceSAXFunc ignorableWhitespace;
+ processingInstructionSAXFunc processingInstruction;
+ commentSAXFunc comment;
+ warningSAXFunc warning;
+ errorSAXFunc error;
+ fatalErrorSAXFunc fatalError; /* unused error() get all the errors */
+ getParameterEntitySAXFunc getParameterEntity;
+ cdataBlockSAXFunc cdataBlock;
+ externalSubsetSAXFunc externalSubset;
+ unsigned int initialized;
+ /* The following fields are extensions available only on version 3 */
+ void *_private;
+ startElementNsSAX2Func startElementNs;
+ endElementNsSAX2Func endElementNs;
+ xmlStructuredErrorFunc serror;
+};
+
+/*
+ * SAX Version 1
+ */
+typedef struct _xmlSAXHandlerV1 xmlSAXHandlerV1;
+typedef xmlSAXHandlerV1 *xmlSAXHandlerV1Ptr;
+struct _xmlSAXHandlerV1 {
+ internalSubsetSAXFunc internalSubset;
+ isStandaloneSAXFunc isStandalone;
+ hasInternalSubsetSAXFunc hasInternalSubset;
+ hasExternalSubsetSAXFunc hasExternalSubset;
+ resolveEntitySAXFunc resolveEntity;
+ getEntitySAXFunc getEntity;
+ entityDeclSAXFunc entityDecl;
+ notationDeclSAXFunc notationDecl;
+ attributeDeclSAXFunc attributeDecl;
+ elementDeclSAXFunc elementDecl;
+ unparsedEntityDeclSAXFunc unparsedEntityDecl;
+ setDocumentLocatorSAXFunc setDocumentLocator;
+ startDocumentSAXFunc startDocument;
+ endDocumentSAXFunc endDocument;
+ startElementSAXFunc startElement;
+ endElementSAXFunc endElement;
+ referenceSAXFunc reference;
+ charactersSAXFunc characters;
+ ignorableWhitespaceSAXFunc ignorableWhitespace;
+ processingInstructionSAXFunc processingInstruction;
+ commentSAXFunc comment;
+ warningSAXFunc warning;
+ errorSAXFunc error;
+ fatalErrorSAXFunc fatalError; /* unused error() get all the errors */
+ getParameterEntitySAXFunc getParameterEntity;
+ cdataBlockSAXFunc cdataBlock;
+ externalSubsetSAXFunc externalSubset;
+ unsigned int initialized;
+};
+
+
+/**
+ * xmlExternalEntityLoader:
+ * @URL: The System ID of the resource requested
+ * @ID: The Public ID of the resource requested
+ * @context: the XML parser context
+ *
+ * External entity loaders types.
+ *
+ * Returns the entity input parser.
+ */
+typedef xmlParserInputPtr (*xmlExternalEntityLoader) (const char *URL,
+ const char *ID,
+ xmlParserCtxtPtr context);
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <libxml/encoding.h>
+#include <libxml/xmlIO.h>
+#include <libxml/globals.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*
+ * Init/Cleanup
+ */
+XMLPUBFUN void XMLCALL
+ xmlInitParser (void);
+XMLPUBFUN void XMLCALL
+ xmlCleanupParser (void);
+
+/*
+ * Input functions
+ */
+XMLPUBFUN int XMLCALL
+ xmlParserInputRead (xmlParserInputPtr in,
+ int len);
+XMLPUBFUN int XMLCALL
+ xmlParserInputGrow (xmlParserInputPtr in,
+ int len);
+
+/*
+ * Basic parsing Interfaces
+ */
+#ifdef LIBXML_SAX1_ENABLED
+XMLPUBFUN xmlDocPtr XMLCALL
+ xmlParseDoc (const xmlChar *cur);
+XMLPUBFUN xmlDocPtr XMLCALL
+ xmlParseFile (const char *filename);
+XMLPUBFUN xmlDocPtr XMLCALL
+ xmlParseMemory (const char *buffer,
+ int size);
+#endif /* LIBXML_SAX1_ENABLED */
+XMLPUBFUN int XMLCALL
+ xmlSubstituteEntitiesDefault(int val);
+XMLPUBFUN int XMLCALL
+ xmlKeepBlanksDefault (int val);
+XMLPUBFUN void XMLCALL
+ xmlStopParser (xmlParserCtxtPtr ctxt);
+XMLPUBFUN int XMLCALL
+ xmlPedanticParserDefault(int val);
+XMLPUBFUN int XMLCALL
+ xmlLineNumbersDefault (int val);
+
+#ifdef LIBXML_SAX1_ENABLED
+/*
+ * Recovery mode
+ */
+XMLPUBFUN xmlDocPtr XMLCALL
+ xmlRecoverDoc (xmlChar *cur);
+XMLPUBFUN xmlDocPtr XMLCALL
+ xmlRecoverMemory (const char *buffer,
+ int size);
+XMLPUBFUN xmlDocPtr XMLCALL
+ xmlRecoverFile (const char *filename);
+#endif /* LIBXML_SAX1_ENABLED */
+
+/*
+ * Less common routines and SAX interfaces
+ */
+XMLPUBFUN int XMLCALL
+ xmlParseDocument (xmlParserCtxtPtr ctxt);
+XMLPUBFUN int XMLCALL
+ xmlParseExtParsedEnt (xmlParserCtxtPtr ctxt);
+#ifdef LIBXML_SAX1_ENABLED
+XMLPUBFUN int XMLCALL
+ xmlSAXUserParseFile (xmlSAXHandlerPtr sax,
+ void *user_data,
+ const char *filename);
+XMLPUBFUN int XMLCALL
+ xmlSAXUserParseMemory (xmlSAXHandlerPtr sax,
+ void *user_data,
+ const char *buffer,
+ int size);
+XMLPUBFUN xmlDocPtr XMLCALL
+ xmlSAXParseDoc (xmlSAXHandlerPtr sax,
+ const xmlChar *cur,
+ int recovery);
+XMLPUBFUN xmlDocPtr XMLCALL
+ xmlSAXParseMemory (xmlSAXHandlerPtr sax,
+ const char *buffer,
+ int size,
+ int recovery);
+XMLPUBFUN xmlDocPtr XMLCALL
+ xmlSAXParseMemoryWithData (xmlSAXHandlerPtr sax,
+ const char *buffer,
+ int size,
+ int recovery,
+ void *data);
+XMLPUBFUN xmlDocPtr XMLCALL
+ xmlSAXParseFile (xmlSAXHandlerPtr sax,
+ const char *filename,
+ int recovery);
+XMLPUBFUN xmlDocPtr XMLCALL
+ xmlSAXParseFileWithData (xmlSAXHandlerPtr sax,
+ const char *filename,
+ int recovery,
+ void *data);
+XMLPUBFUN xmlDocPtr XMLCALL
+ xmlSAXParseEntity (xmlSAXHandlerPtr sax,
+ const char *filename);
+XMLPUBFUN xmlDocPtr XMLCALL
+ xmlParseEntity (const char *filename);
+#endif /* LIBXML_SAX1_ENABLED */
+
+#ifdef LIBXML_VALID_ENABLED
+XMLPUBFUN xmlDtdPtr XMLCALL
+ xmlSAXParseDTD (xmlSAXHandlerPtr sax,
+ const xmlChar *ExternalID,
+ const xmlChar *SystemID);
+XMLPUBFUN xmlDtdPtr XMLCALL
+ xmlParseDTD (const xmlChar *ExternalID,
+ const xmlChar *SystemID);
+XMLPUBFUN xmlDtdPtr XMLCALL
+ xmlIOParseDTD (xmlSAXHandlerPtr sax,
+ xmlParserInputBufferPtr input,
+ xmlCharEncoding enc);
+#endif /* LIBXML_VALID_ENABLE */
+#ifdef LIBXML_SAX1_ENABLED
+XMLPUBFUN int XMLCALL
+ xmlParseBalancedChunkMemory(xmlDocPtr doc,
+ xmlSAXHandlerPtr sax,
+ void *user_data,
+ int depth,
+ const xmlChar *string,
+ xmlNodePtr *lst);
+#endif /* LIBXML_SAX1_ENABLED */
+XMLPUBFUN xmlParserErrors XMLCALL
+ xmlParseInNodeContext (xmlNodePtr node,
+ const char *data,
+ int datalen,
+ int options,
+ xmlNodePtr *lst);
+#ifdef LIBXML_SAX1_ENABLED
+XMLPUBFUN int XMLCALL
+ xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc,
+ xmlSAXHandlerPtr sax,
+ void *user_data,
+ int depth,
+ const xmlChar *string,
+ xmlNodePtr *lst,
+ int recover);
+XMLPUBFUN int XMLCALL
+ xmlParseExternalEntity (xmlDocPtr doc,
+ xmlSAXHandlerPtr sax,
+ void *user_data,
+ int depth,
+ const xmlChar *URL,
+ const xmlChar *ID,
+ xmlNodePtr *lst);
+#endif /* LIBXML_SAX1_ENABLED */
+XMLPUBFUN int XMLCALL
+ xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx,
+ const xmlChar *URL,
+ const xmlChar *ID,
+ xmlNodePtr *lst);
+
+/*
+ * Parser contexts handling.
+ */
+XMLPUBFUN xmlParserCtxtPtr XMLCALL
+ xmlNewParserCtxt (void);
+XMLPUBFUN int XMLCALL
+ xmlInitParserCtxt (xmlParserCtxtPtr ctxt);
+XMLPUBFUN void XMLCALL
+ xmlClearParserCtxt (xmlParserCtxtPtr ctxt);
+XMLPUBFUN void XMLCALL
+ xmlFreeParserCtxt (xmlParserCtxtPtr ctxt);
+#ifdef LIBXML_SAX1_ENABLED
+XMLPUBFUN void XMLCALL
+ xmlSetupParserForBuffer (xmlParserCtxtPtr ctxt,
+ const xmlChar* buffer,
+ const char *filename);
+#endif /* LIBXML_SAX1_ENABLED */
+XMLPUBFUN xmlParserCtxtPtr XMLCALL
+ xmlCreateDocParserCtxt (const xmlChar *cur);
+
+#ifdef LIBXML_LEGACY_ENABLED
+/*
+ * Reading/setting optional parsing features.
+ */
+XMLPUBFUN int XMLCALL
+ xmlGetFeaturesList (int *len,
+ const char **result);
+XMLPUBFUN int XMLCALL
+ xmlGetFeature (xmlParserCtxtPtr ctxt,
+ const char *name,
+ void *result);
+XMLPUBFUN int XMLCALL
+ xmlSetFeature (xmlParserCtxtPtr ctxt,
+ const char *name,
+ void *value);
+#endif /* LIBXML_LEGACY_ENABLED */
+
+#ifdef LIBXML_PUSH_ENABLED
+/*
+ * Interfaces for the Push mode.
+ */
+XMLPUBFUN xmlParserCtxtPtr XMLCALL
+ xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax,
+ void *user_data,
+ const char *chunk,
+ int size,
+ const char *filename);
+XMLPUBFUN int XMLCALL
+ xmlParseChunk (xmlParserCtxtPtr ctxt,
+ const char *chunk,
+ int size,
+ int terminate);
+#endif /* LIBXML_PUSH_ENABLED */
+
+/*
+ * Special I/O mode.
+ */
+
+XMLPUBFUN xmlParserCtxtPtr XMLCALL
+ xmlCreateIOParserCtxt (xmlSAXHandlerPtr sax,
+ void *user_data,
+ xmlInputReadCallback ioread,
+ xmlInputCloseCallback ioclose,
+ void *ioctx,
+ xmlCharEncoding enc);
+
+XMLPUBFUN xmlParserInputPtr XMLCALL
+ xmlNewIOInputStream (xmlParserCtxtPtr ctxt,
+ xmlParserInputBufferPtr input,
+ xmlCharEncoding enc);
+
+/*
+ * Node infos.
+ */
+XMLPUBFUN const xmlParserNodeInfo* XMLCALL
+ xmlParserFindNodeInfo (const xmlParserCtxtPtr ctxt,
+ const xmlNodePtr node);
+XMLPUBFUN void XMLCALL
+ xmlInitNodeInfoSeq (xmlParserNodeInfoSeqPtr seq);
+XMLPUBFUN void XMLCALL
+ xmlClearNodeInfoSeq (xmlParserNodeInfoSeqPtr seq);
+XMLPUBFUN unsigned long XMLCALL
+ xmlParserFindNodeInfoIndex(const xmlParserNodeInfoSeqPtr seq,
+ const xmlNodePtr node);
+XMLPUBFUN void XMLCALL
+ xmlParserAddNodeInfo (xmlParserCtxtPtr ctxt,
+ const xmlParserNodeInfoPtr info);
+
+/*
+ * External entities handling actually implemented in xmlIO.
+ */
+
+XMLPUBFUN void XMLCALL
+ xmlSetExternalEntityLoader(xmlExternalEntityLoader f);
+XMLPUBFUN xmlExternalEntityLoader XMLCALL
+ xmlGetExternalEntityLoader(void);
+XMLPUBFUN xmlParserInputPtr XMLCALL
+ xmlLoadExternalEntity (const char *URL,
+ const char *ID,
+ xmlParserCtxtPtr ctxt);
+
+/*
+ * Index lookup, actually implemented in the encoding module
+ */
+XMLPUBFUN long XMLCALL
+ xmlByteConsumed (xmlParserCtxtPtr 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 {
+ XML_PARSE_RECOVER = 1<<0, /* recover on errors */
+ XML_PARSE_NOENT = 1<<1, /* substitute entities */
+ XML_PARSE_DTDLOAD = 1<<2, /* load the external subset */
+ XML_PARSE_DTDATTR = 1<<3, /* default DTD attributes */
+ XML_PARSE_DTDVALID = 1<<4, /* validate with the DTD */
+ XML_PARSE_NOERROR = 1<<5, /* suppress error reports */
+ XML_PARSE_NOWARNING = 1<<6, /* suppress warning reports */
+ XML_PARSE_PEDANTIC = 1<<7, /* pedantic error reporting */
+ XML_PARSE_NOBLANKS = 1<<8, /* remove blank nodes */
+ XML_PARSE_SAX1 = 1<<9, /* use the SAX1 interface internally */
+ XML_PARSE_XINCLUDE = 1<<10,/* Implement XInclude substitition */
+ XML_PARSE_NONET = 1<<11,/* Forbid network access */
+ XML_PARSE_NODICT = 1<<12,/* Do not reuse the context dictionnary */
+ XML_PARSE_NSCLEAN = 1<<13,/* remove redundant namespaces declarations */
+ XML_PARSE_NOCDATA = 1<<14,/* merge CDATA as text nodes */
+ XML_PARSE_NOXINCNODE= 1<<15,/* do not generate XINCLUDE START/END nodes */
+ XML_PARSE_COMPACT = 1<<16 /* compact small text nodes; no modification of
+ the tree allowed afterwards (will possibly
+ crash if you try to modify the tree) */
+} xmlParserOption;
+
+XMLPUBFUN void XMLCALL
+ xmlCtxtReset (xmlParserCtxtPtr ctxt);
+XMLPUBFUN int XMLCALL
+ xmlCtxtResetPush (xmlParserCtxtPtr ctxt,
+ const char *chunk,
+ int size,
+ const char *filename,
+ const char *encoding);
+XMLPUBFUN int XMLCALL
+ xmlCtxtUseOptions (xmlParserCtxtPtr ctxt,
+ int options);
+XMLPUBFUN xmlDocPtr XMLCALL
+ xmlReadDoc (const xmlChar *cur,
+ const char *URL,
+ const char *encoding,
+ int options);
+XMLPUBFUN xmlDocPtr XMLCALL
+ xmlReadFile (const char *URL,
+ const char *encoding,
+ int options);
+XMLPUBFUN xmlDocPtr XMLCALL
+ xmlReadMemory (const char *buffer,
+ int size,
+ const char *URL,
+ const char *encoding,
+ int options);
+XMLPUBFUN xmlDocPtr XMLCALL
+ xmlReadFd (int fd,
+ const char *URL,
+ const char *encoding,
+ int options);
+XMLPUBFUN xmlDocPtr XMLCALL
+ xmlReadIO (xmlInputReadCallback ioread,
+ xmlInputCloseCallback ioclose,
+ void *ioctx,
+ const char *URL,
+ const char *encoding,
+ int options);
+XMLPUBFUN xmlDocPtr XMLCALL
+ xmlCtxtReadDoc (xmlParserCtxtPtr ctxt,
+ const xmlChar *cur,
+ const char *URL,
+ const char *encoding,
+ int options);
+XMLPUBFUN xmlDocPtr XMLCALL
+ xmlCtxtReadFile (xmlParserCtxtPtr ctxt,
+ const char *filename,
+ const char *encoding,
+ int options);
+XMLPUBFUN xmlDocPtr XMLCALL
+ xmlCtxtReadMemory (xmlParserCtxtPtr ctxt,
+ const char *buffer,
+ int size,
+ const char *URL,
+ const char *encoding,
+ int options);
+XMLPUBFUN xmlDocPtr XMLCALL
+ xmlCtxtReadFd (xmlParserCtxtPtr ctxt,
+ int fd,
+ const char *URL,
+ const char *encoding,
+ int options);
+XMLPUBFUN xmlDocPtr XMLCALL
+ xmlCtxtReadIO (xmlParserCtxtPtr ctxt,
+ xmlInputReadCallback ioread,
+ xmlInputCloseCallback ioclose,
+ void *ioctx,
+ const char *URL,
+ const char *encoding,
+ int options);
+
+/*
+ * Library wide options
+ */
+/**
+ * xmlFeature:
+ *
+ * Used to examine the existance of features that can be enabled
+ * or disabled at compile-time.
+ * They used to be called XML_FEATURE_xxx but this clashed with Expat
+ */
+typedef enum {
+ XML_WITH_THREAD = 1,
+ XML_WITH_TREE = 2,
+ XML_WITH_OUTPUT = 3,
+ XML_WITH_PUSH = 4,
+ XML_WITH_READER = 5,
+ XML_WITH_PATTERN = 6,
+ XML_WITH_WRITER = 7,
+ XML_WITH_SAX1 = 8,
+ XML_WITH_FTP = 9,
+ XML_WITH_HTTP = 10,
+ XML_WITH_VALID = 11,
+ XML_WITH_HTML = 12,
+ XML_WITH_LEGACY = 13,
+ XML_WITH_C14N = 14,
+ XML_WITH_CATALOG = 15,
+ XML_WITH_XPATH = 16,
+ XML_WITH_XPTR = 17,
+ XML_WITH_XINCLUDE = 18,
+ XML_WITH_ICONV = 19,
+ XML_WITH_ISO8859X = 20,
+ XML_WITH_UNICODE = 21,
+ XML_WITH_REGEXP = 22,
+ XML_WITH_AUTOMATA = 23,
+ XML_WITH_EXPR = 24,
+ XML_WITH_SCHEMAS = 25,
+ XML_WITH_SCHEMATRON = 26,
+ XML_WITH_MODULES = 27,
+ XML_WITH_DEBUG = 28,
+ XML_WITH_DEBUG_MEM = 29,
+ XML_WITH_DEBUG_RUN = 30,
+ XML_WITH_ZLIB = 31,
+ XML_WITH_NONE = 99999 /* just to be sure of allocation size */
+} xmlFeature;
+
+XMLPUBFUN int XMLCALL
+ xmlHasFeature (xmlFeature feature);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __XML_PARSER_H__ */
+
diff --git a/gettext-tools/gnulib-lib/libxml/parserInternals.c b/gettext-tools/gnulib-lib/libxml/parserInternals.c
new file mode 100644
index 0000000..f4da58d
--- /dev/null
+++ b/gettext-tools/gnulib-lib/libxml/parserInternals.c
@@ -0,0 +1,2061 @@
+/*
+ * parserInternals.c : Internal routines (and obsolete ones) needed for the
+ * XML and HTML parsers.
+ *
+ * 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 <string.h>
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_ZLIB_H
+#include <zlib.h>
+#endif
+
+#include <libxml/xmlmemory.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/valid.h>
+#include <libxml/entities.h>
+#include <libxml/xmlerror.h>
+#include <libxml/encoding.h>
+#include <libxml/valid.h>
+#include <libxml/xmlIO.h>
+#include <libxml/uri.h>
+#include <libxml/dict.h>
+#include <libxml/SAX.h>
+#ifdef LIBXML_CATALOG_ENABLED
+#include <libxml/catalog.h>
+#endif
+#include <libxml/globals.h>
+#include <libxml/chvalid.h>
+
+/*
+ * Various global defaults for parsing
+ */
+
+/**
+ * xmlCheckVersion:
+ * @version: the include version number
+ *
+ * check the compiled lib version against the include one.
+ * This can warn or immediately kill the application
+ */
+void
+xmlCheckVersion(int version) {
+ int myversion = (int) LIBXML_VERSION;
+
+ xmlInitParser();
+
+ if ((myversion / 10000) != (version / 10000)) {
+ xmlGenericError(xmlGenericErrorContext,
+ "Fatal: program compiled against libxml %d using libxml %d\n",
+ (version / 10000), (myversion / 10000));
+ fprintf(stderr,
+ "Fatal: program compiled against libxml %d using libxml %d\n",
+ (version / 10000), (myversion / 10000));
+ }
+ if ((myversion / 100) < (version / 100)) {
+ xmlGenericError(xmlGenericErrorContext,
+ "Warning: program compiled against libxml %d using older %d\n",
+ (version / 100), (myversion / 100));
+ }
+}
+
+
+/************************************************************************
+ * *
+ * Some factorized error routines *
+ * *
+ ************************************************************************/
+
+
+/**
+ * xmlErrMemory:
+ * @ctxt: an XML parser context
+ * @extra: extra informations
+ *
+ * Handle a redefinition of attribute error
+ */
+void
+xmlErrMemory(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");
+}
+
+/**
+ * __xmlErrEncoding:
+ * @ctxt: an XML parser context
+ * @xmlerr: the error number
+ * @msg: the error message
+ * @str1: an string info
+ * @str2: an string info
+ *
+ * Handle an encoding error
+ */
+void
+__xmlErrEncoding(xmlParserCtxtPtr ctxt, xmlParserErrors xmlerr,
+ 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 = xmlerr;
+ __xmlRaiseError(NULL, NULL, NULL,
+ ctxt, NULL, XML_FROM_PARSER, xmlerr, XML_ERR_FATAL,
+ NULL, 0, (const char *) str1, (const char *) str2,
+ NULL, 0, 0, msg, str1, str2);
+ if (ctxt != NULL) {
+ ctxt->wellFormed = 0;
+ if (ctxt->recovery == 0)
+ ctxt->disableSAX = 1;
+ }
+}
+
+/**
+ * xmlErrInternal:
+ * @ctxt: an XML parser context
+ * @msg: the error message
+ * @str: error informations
+ *
+ * Handle an internal error
+ */
+static void
+xmlErrInternal(xmlParserCtxtPtr ctxt, const char *msg, const xmlChar * str)
+{
+ if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
+ (ctxt->instate == XML_PARSER_EOF))
+ return;
+ if (ctxt != NULL)
+ ctxt->errNo = XML_ERR_INTERNAL_ERROR;
+ __xmlRaiseError(NULL, NULL, NULL,
+ ctxt, NULL, XML_FROM_PARSER, XML_ERR_INTERNAL_ERROR,
+ XML_ERR_FATAL, NULL, 0, (const char *) str, NULL, NULL,
+ 0, 0, msg, str);
+ if (ctxt != NULL) {
+ ctxt->wellFormed = 0;
+ if (ctxt->recovery == 0)
+ ctxt->disableSAX = 1;
+ }
+}
+
+/**
+ * xmlErrEncodingInt:
+ * @ctxt: an XML parser context
+ * @error: the error number
+ * @msg: the error message
+ * @val: an integer value
+ *
+ * n encoding error
+ */
+static void
+xmlErrEncodingInt(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;
+ }
+}
+
+/**
+ * xmlIsLetter:
+ * @c: an unicode character (int)
+ *
+ * Check whether the character is allowed by the production
+ * [84] Letter ::= BaseChar | Ideographic
+ *
+ * Returns 0 if not, non-zero otherwise
+ */
+int
+xmlIsLetter(int c) {
+ return(IS_BASECHAR(c) || IS_IDEOGRAPHIC(c));
+}
+
+/************************************************************************
+ * *
+ * Input handling functions for progressive parsing *
+ * *
+ ************************************************************************/
+
+/* #define DEBUG_INPUT */
+/* #define DEBUG_STACK */
+/* #define DEBUG_PUSH */
+
+
+/* we need to keep enough input to show errors in context */
+#define LINE_LEN 80
+
+#ifdef DEBUG_INPUT
+#define CHECK_BUFFER(in) check_buffer(in)
+
+static
+void check_buffer(xmlParserInputPtr in) {
+ if (in->base != in->buf->buffer->content) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlParserInput: base mismatch problem\n");
+ }
+ if (in->cur < in->base) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlParserInput: cur < base problem\n");
+ }
+ if (in->cur > in->base + in->buf->buffer->use) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlParserInput: cur > base + use problem\n");
+ }
+ xmlGenericError(xmlGenericErrorContext,"buffer %x : content %x, cur %d, use %d, size %d\n",
+ (int) in, (int) in->buf->buffer->content, in->cur - in->base,
+ in->buf->buffer->use, in->buf->buffer->size);
+}
+
+#else
+#define CHECK_BUFFER(in)
+#endif
+
+
+/**
+ * xmlParserInputRead:
+ * @in: an XML parser input
+ * @len: an indicative size for the lookahead
+ *
+ * This function refresh the input for the parser. It doesn't try to
+ * preserve pointers to the input buffer, and discard already read data
+ *
+ * Returns the number of xmlChars read, or -1 in case of error, 0 indicate the
+ * end of this entity
+ */
+int
+xmlParserInputRead(xmlParserInputPtr in, int len) {
+ int ret;
+ int used;
+ int indx;
+
+ if (in == NULL) return(-1);
+#ifdef DEBUG_INPUT
+ xmlGenericError(xmlGenericErrorContext, "Read\n");
+#endif
+ if (in->buf == NULL) return(-1);
+ if (in->base == NULL) return(-1);
+ if (in->cur == NULL) return(-1);
+ if (in->buf->buffer == NULL) return(-1);
+ if (in->buf->readcallback == NULL) return(-1);
+
+ CHECK_BUFFER(in);
+
+ used = in->cur - in->buf->buffer->content;
+ ret = xmlBufferShrink(in->buf->buffer, used);
+ if (ret > 0) {
+ in->cur -= ret;
+ in->consumed += ret;
+ }
+ ret = xmlParserInputBufferRead(in->buf, len);
+ if (in->base != in->buf->buffer->content) {
+ /*
+ * the buffer has been reallocated
+ */
+ indx = in->cur - in->base;
+ in->base = in->buf->buffer->content;
+ in->cur = &in->buf->buffer->content[indx];
+ }
+ in->end = &in->buf->buffer->content[in->buf->buffer->use];
+
+ CHECK_BUFFER(in);
+
+ return(ret);
+}
+
+/**
+ * xmlParserInputGrow:
+ * @in: an XML parser input
+ * @len: an indicative size for the lookahead
+ *
+ * This function increase the input for the parser. It tries to
+ * preserve pointers to the input buffer, and keep already read data
+ *
+ * Returns the number of xmlChars read, or -1 in case of error, 0 indicate the
+ * end of this entity
+ */
+int
+xmlParserInputGrow(xmlParserInputPtr in, int len) {
+ int ret;
+ int indx;
+
+ if (in == NULL) return(-1);
+#ifdef DEBUG_INPUT
+ xmlGenericError(xmlGenericErrorContext, "Grow\n");
+#endif
+ if (in->buf == NULL) return(-1);
+ if (in->base == NULL) return(-1);
+ if (in->cur == NULL) return(-1);
+ if (in->buf->buffer == NULL) return(-1);
+
+ CHECK_BUFFER(in);
+
+ indx = in->cur - in->base;
+ if (in->buf->buffer->use > (unsigned int) indx + INPUT_CHUNK) {
+
+ CHECK_BUFFER(in);
+
+ return(0);
+ }
+ if (in->buf->readcallback != NULL)
+ ret = xmlParserInputBufferGrow(in->buf, len);
+ else
+ return(0);
+
+ /*
+ * NOTE : in->base may be a "dangling" i.e. freed pointer in this
+ * block, but we use it really as an integer to do some
+ * pointer arithmetic. Insure will raise it as a bug but in
+ * that specific case, that's not !
+ */
+ if (in->base != in->buf->buffer->content) {
+ /*
+ * the buffer has been reallocated
+ */
+ indx = in->cur - in->base;
+ in->base = in->buf->buffer->content;
+ in->cur = &in->buf->buffer->content[indx];
+ }
+ in->end = &in->buf->buffer->content[in->buf->buffer->use];
+
+ CHECK_BUFFER(in);
+
+ return(ret);
+}
+
+/**
+ * xmlParserInputShrink:
+ * @in: an XML parser input
+ *
+ * This function removes used input for the parser.
+ */
+void
+xmlParserInputShrink(xmlParserInputPtr in) {
+ int used;
+ int ret;
+ int indx;
+
+#ifdef DEBUG_INPUT
+ xmlGenericError(xmlGenericErrorContext, "Shrink\n");
+#endif
+ if (in == NULL) return;
+ if (in->buf == NULL) return;
+ if (in->base == NULL) return;
+ if (in->cur == NULL) return;
+ if (in->buf->buffer == NULL) return;
+
+ CHECK_BUFFER(in);
+
+ used = in->cur - in->buf->buffer->content;
+ /*
+ * Do not shrink on large buffers whose only a tiny fraction
+ * was consumed
+ */
+ if (used > INPUT_CHUNK) {
+ ret = xmlBufferShrink(in->buf->buffer, used - LINE_LEN);
+ if (ret > 0) {
+ in->cur -= ret;
+ in->consumed += ret;
+ }
+ in->end = &in->buf->buffer->content[in->buf->buffer->use];
+ }
+
+ CHECK_BUFFER(in);
+
+ if (in->buf->buffer->use > INPUT_CHUNK) {
+ return;
+ }
+ xmlParserInputBufferRead(in->buf, 2 * INPUT_CHUNK);
+ if (in->base != in->buf->buffer->content) {
+ /*
+ * the buffer has been reallocated
+ */
+ indx = in->cur - in->base;
+ in->base = in->buf->buffer->content;
+ in->cur = &in->buf->buffer->content[indx];
+ }
+ in->end = &in->buf->buffer->content[in->buf->buffer->use];
+
+ CHECK_BUFFER(in);
+}
+
+/************************************************************************
+ * *
+ * UTF8 character input and related functions *
+ * *
+ ************************************************************************/
+
+/**
+ * xmlNextChar:
+ * @ctxt: the XML parser context
+ *
+ * Skip to the next char input char.
+ */
+
+void
+xmlNextChar(xmlParserCtxtPtr ctxt)
+{
+ if ((ctxt == NULL) || (ctxt->instate == XML_PARSER_EOF) ||
+ (ctxt->input == NULL))
+ return;
+
+ if (ctxt->charset == XML_CHAR_ENCODING_UTF8) {
+ if ((*ctxt->input->cur == 0) &&
+ (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0) &&
+ (ctxt->instate != XML_PARSER_COMMENT)) {
+ /*
+ * If we are at the end of the current entity and
+ * the context allows it, we pop consumed entities
+ * automatically.
+ * the auto closing should be blocked in other cases
+ */
+ xmlPopInput(ctxt);
+ } else {
+ const unsigned char *cur;
+ unsigned char c;
+
+ /*
+ * 2.11 End-of-Line Handling
+ * the literal two-character sequence "#xD#xA" or a standalone
+ * literal #xD, an XML processor must pass to the application
+ * the single character #xA.
+ */
+ if (*(ctxt->input->cur) == '\n') {
+ ctxt->input->line++; ctxt->input->col = 1;
+ } else
+ ctxt->input->col++;
+
+ /*
+ * 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
+ */
+ cur = ctxt->input->cur;
+
+ c = *cur;
+ if (c & 0x80) {
+ if (c == 0xC0)
+ goto encoding_error;
+ if (cur[1] == 0)
+ xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
+ if ((cur[1] & 0xc0) != 0x80)
+ goto encoding_error;
+ if ((c & 0xe0) == 0xe0) {
+ unsigned int val;
+
+ 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 */
+ ctxt->input->cur += 4;
+ val = (cur[0] & 0x7) << 18;
+ val |= (cur[1] & 0x3f) << 12;
+ val |= (cur[2] & 0x3f) << 6;
+ val |= cur[3] & 0x3f;
+ } else {
+ /* 3-byte code */
+ ctxt->input->cur += 3;
+ val = (cur[0] & 0xf) << 12;
+ val |= (cur[1] & 0x3f) << 6;
+ val |= cur[2] & 0x3f;
+ }
+ if (((val > 0xd7ff) && (val < 0xe000)) ||
+ ((val > 0xfffd) && (val < 0x10000)) ||
+ (val >= 0x110000)) {
+ xmlErrEncodingInt(ctxt, XML_ERR_INVALID_CHAR,
+ "Char 0x%X out of allowed range\n",
+ val);
+ }
+ } else
+ /* 2-byte code */
+ ctxt->input->cur += 2;
+ } else
+ /* 1-byte code */
+ ctxt->input->cur++;
+
+ ctxt->nbChars++;
+ if (*ctxt->input->cur == 0)
+ xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
+ }
+ } else {
+ /*
+ * Assume it's a fixed length encoding (1) with
+ * a compatible encoding for the ASCII set, since
+ * XML constructs only use < 128 chars
+ */
+
+ 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);
+ }
+ if ((*ctxt->input->cur == '%') && (!ctxt->html))
+ xmlParserHandlePEReference(ctxt);
+ if ((*ctxt->input->cur == 0) &&
+ (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
+ xmlPopInput(ctxt);
+ return;
+encoding_error:
+ /*
+ * If we detect an UTF8 error that probably mean 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 !)
+ */
+ if ((ctxt == NULL) || (ctxt->input == NULL) ||
+ (ctxt->input->end - ctxt->input->cur < 4)) {
+ __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
+ "Input is not proper UTF-8, indicate encoding !\n",
+ NULL, NULL);
+ } else {
+ 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]);
+ __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
+ "Input is not proper UTF-8, indicate encoding !\n%s",
+ BAD_CAST buffer, NULL);
+ }
+ ctxt->charset = XML_CHAR_ENCODING_8859_1;
+ ctxt->input->cur++;
+ return;
+}
+
+/**
+ * xmlCurrentChar:
+ * @ctxt: the XML 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
+ * Wherever an external parsed entity or the literal entity value
+ * of an internal parsed entity contains either the literal two-character
+ * sequence "#xD#xA" or a standalone literal #xD, an XML processor
+ * must pass to the application the single character #xA.
+ * This behavior can conveniently be produced by normalizing all
+ * line breaks to #xA on input, before parsing.)
+ *
+ * Returns the current char value and its length
+ */
+
+int
+xmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) {
+ if ((ctxt == NULL) || (len == NULL) || (ctxt->input == NULL)) return(0);
+ if (ctxt->instate == XML_PARSER_EOF)
+ return(0);
+
+ if ((*ctxt->input->cur >= 0x20) && (*ctxt->input->cur <= 0x7F)) {
+ *len = 1;
+ return((int) *ctxt->input->cur);
+ }
+ 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 (c == 0xC0)
+ goto encoding_error;
+ 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)) {
+ xmlErrEncodingInt(ctxt, XML_ERR_INVALID_CHAR,
+ "Char 0x%X out of allowed range\n", val);
+ }
+ return(val);
+ } else {
+ /* 1-byte code */
+ *len = 1;
+ if (*ctxt->input->cur == 0xD) {
+ if (ctxt->input->cur[1] == 0xA) {
+ ctxt->nbChars++;
+ ctxt->input->cur++;
+ }
+ return(0xA);
+ }
+ 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 (*ctxt->input->cur == 0xD) {
+ if (ctxt->input->cur[1] == 0xA) {
+ ctxt->nbChars++;
+ ctxt->input->cur++;
+ }
+ return(0xA);
+ }
+ return((int) *ctxt->input->cur);
+encoding_error:
+ /*
+ * An encoding problem may arise from a truncated input buffer
+ * splitting a character in the middle. In that case do not raise
+ * an error but return 0 to endicate an end of stream problem
+ */
+ if (ctxt->input->end - ctxt->input->cur < 4) {
+ *len = 0;
+ return(0);
+ }
+
+ /*
+ * If we detect an UTF8 error that probably mean 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 !)
+ */
+ {
+ char buffer[150];
+
+ snprintf(&buffer[0], 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]);
+ __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
+ "Input is not proper UTF-8, indicate encoding !\n%s",
+ BAD_CAST buffer, NULL);
+ }
+ ctxt->charset = XML_CHAR_ENCODING_8859_1;
+ *len = 1;
+ return((int) *ctxt->input->cur);
+}
+
+/**
+ * xmlStringCurrentChar:
+ * @ctxt: the XML 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
+ */
+
+int
+xmlStringCurrentChar(xmlParserCtxtPtr ctxt, const xmlChar * cur, int *len)
+{
+ if ((len == NULL) || (cur == NULL)) return(0);
+ if ((ctxt == NULL) || (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
+ */
+ unsigned char c;
+ unsigned int val;
+
+ 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)) {
+ xmlErrEncodingInt(ctxt, XML_ERR_INVALID_CHAR,
+ "Char 0x%X out of allowed range\n", val);
+ }
+ return (val);
+ } else {
+ /* 1-byte code */
+ *len = 1;
+ return ((int) *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;
+ return ((int) *cur);
+encoding_error:
+
+ /*
+ * An encoding problem may arise from a truncated input buffer
+ * splitting a character in the middle. In that case do not raise
+ * an error but return 0 to endicate an end of stream problem
+ */
+ if ((ctxt == NULL) || (ctxt->input == NULL) ||
+ (ctxt->input->end - ctxt->input->cur < 4)) {
+ *len = 0;
+ return(0);
+ }
+ /*
+ * If we detect an UTF8 error that probably mean 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 !)
+ */
+ {
+ 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]);
+ __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
+ "Input is not proper UTF-8, indicate encoding !\n%s",
+ BAD_CAST buffer, NULL);
+ }
+ *len = 1;
+ return ((int) *cur);
+}
+
+/**
+ * xmlCopyCharMultiByte:
+ * @out: pointer to an array of xmlChar
+ * @val: the char value
+ *
+ * append the char value in the array
+ *
+ * Returns the number of xmlChar written
+ */
+int
+xmlCopyCharMultiByte(xmlChar *out, int val) {
+ if (out == NULL) return(0);
+ /*
+ * 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
+ */
+ if (val >= 0x80) {
+ xmlChar *savedout = out;
+ int bits;
+ if (val < 0x800) { *out++= (val >> 6) | 0xC0; bits= 0; }
+ else if (val < 0x10000) { *out++= (val >> 12) | 0xE0; bits= 6;}
+ else if (val < 0x110000) { *out++= (val >> 18) | 0xF0; bits= 12; }
+ else {
+ xmlErrEncodingInt(NULL, XML_ERR_INVALID_CHAR,
+ "Internal error, xmlCopyCharMultiByte 0x%X out of bound\n",
+ val);
+ return(0);
+ }
+ for ( ; bits >= 0; bits-= 6)
+ *out++= ((val >> bits) & 0x3F) | 0x80 ;
+ return (out - savedout);
+ }
+ *out = (xmlChar) val;
+ return 1;
+}
+
+/**
+ * xmlCopyChar:
+ * @len: Ignored, compatibility
+ * @out: pointer to an array of xmlChar
+ * @val: the char value
+ *
+ * append the char value in the array
+ *
+ * Returns the number of xmlChar written
+ */
+
+int
+xmlCopyChar(int len ATTRIBUTE_UNUSED, xmlChar *out, int val) {
+ if (out == NULL) return(0);
+ /* the len parameter is ignored */
+ if (val >= 0x80) {
+ return(xmlCopyCharMultiByte (out, val));
+ }
+ *out = (xmlChar) val;
+ return 1;
+}
+
+/************************************************************************
+ * *
+ * Commodity functions to switch encodings *
+ * *
+ ************************************************************************/
+
+/**
+ * xmlSwitchEncoding:
+ * @ctxt: the parser context
+ * @enc: the encoding value (number)
+ *
+ * change the input functions when discovering the character encoding
+ * of a given entity.
+ *
+ * Returns 0 in case of success, -1 otherwise
+ */
+int
+xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc)
+{
+ xmlCharEncodingHandlerPtr handler;
+
+ if (ctxt == NULL) return(-1);
+ switch (enc) {
+ case XML_CHAR_ENCODING_ERROR:
+ __xmlErrEncoding(ctxt, XML_ERR_UNKNOWN_ENCODING,
+ "encoding unknown\n", NULL, NULL);
+ return(-1);
+ case XML_CHAR_ENCODING_NONE:
+ /* let's assume it's UTF-8 without the XML decl */
+ ctxt->charset = XML_CHAR_ENCODING_UTF8;
+ return(0);
+ case XML_CHAR_ENCODING_UTF8:
+ /* default encoding, no conversion should be needed */
+ ctxt->charset = XML_CHAR_ENCODING_UTF8;
+
+ /*
+ * Errata on XML-1.0 June 20 2001
+ * Specific handling of the Byte Order Mark for
+ * UTF-8
+ */
+ if ((ctxt->input != NULL) &&
+ (ctxt->input->cur[0] == 0xEF) &&
+ (ctxt->input->cur[1] == 0xBB) &&
+ (ctxt->input->cur[2] == 0xBF)) {
+ ctxt->input->cur += 3;
+ }
+ return(0);
+ case XML_CHAR_ENCODING_UTF16LE:
+ case XML_CHAR_ENCODING_UTF16BE:
+ /*The raw input characters are encoded
+ *in UTF-16. As we expect this function
+ *to be called after xmlCharEncInFunc, we expect
+ *ctxt->input->cur to contain UTF-8 encoded characters.
+ *So the raw UTF16 Byte Order Mark
+ *has also been converted into
+ *an UTF-8 BOM. Let's skip that BOM.
+ */
+ if ((ctxt->input != NULL) && (ctxt->input->cur != NULL) &&
+ (ctxt->input->cur[0] == 0xEF) &&
+ (ctxt->input->cur[1] == 0xBB) &&
+ (ctxt->input->cur[2] == 0xBF)) {
+ ctxt->input->cur += 3;
+ }
+ break ;
+ default:
+ break;
+ }
+ handler = xmlGetCharEncodingHandler(enc);
+ if (handler == NULL) {
+ /*
+ * Default handlers.
+ */
+ switch (enc) {
+ case XML_CHAR_ENCODING_ASCII:
+ /* default encoding, no conversion should be needed */
+ ctxt->charset = XML_CHAR_ENCODING_UTF8;
+ return(0);
+ case XML_CHAR_ENCODING_UTF16LE:
+ break;
+ case XML_CHAR_ENCODING_UTF16BE:
+ break;
+ case XML_CHAR_ENCODING_UCS4LE:
+ __xmlErrEncoding(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
+ "encoding not supported %s\n",
+ BAD_CAST "USC4 little endian", NULL);
+ break;
+ case XML_CHAR_ENCODING_UCS4BE:
+ __xmlErrEncoding(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
+ "encoding not supported %s\n",
+ BAD_CAST "USC4 big endian", NULL);
+ break;
+ case XML_CHAR_ENCODING_EBCDIC:
+ __xmlErrEncoding(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
+ "encoding not supported %s\n",
+ BAD_CAST "EBCDIC", NULL);
+ break;
+ case XML_CHAR_ENCODING_UCS4_2143:
+ __xmlErrEncoding(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
+ "encoding not supported %s\n",
+ BAD_CAST "UCS4 2143", NULL);
+ break;
+ case XML_CHAR_ENCODING_UCS4_3412:
+ __xmlErrEncoding(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
+ "encoding not supported %s\n",
+ BAD_CAST "UCS4 3412", NULL);
+ break;
+ case XML_CHAR_ENCODING_UCS2:
+ __xmlErrEncoding(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
+ "encoding not supported %s\n",
+ BAD_CAST "UCS2", NULL);
+ break;
+ case XML_CHAR_ENCODING_8859_1:
+ case XML_CHAR_ENCODING_8859_2:
+ case XML_CHAR_ENCODING_8859_3:
+ case XML_CHAR_ENCODING_8859_4:
+ case XML_CHAR_ENCODING_8859_5:
+ case XML_CHAR_ENCODING_8859_6:
+ case XML_CHAR_ENCODING_8859_7:
+ case XML_CHAR_ENCODING_8859_8:
+ case XML_CHAR_ENCODING_8859_9:
+ /*
+ * We used to keep the internal content in the
+ * document encoding however this turns being unmaintainable
+ * So xmlGetCharEncodingHandler() will return non-null
+ * values for this now.
+ */
+ if ((ctxt->inputNr == 1) &&
+ (ctxt->encoding == NULL) &&
+ (ctxt->input != NULL) &&
+ (ctxt->input->encoding != NULL)) {
+ ctxt->encoding = xmlStrdup(ctxt->input->encoding);
+ }
+ ctxt->charset = enc;
+ return(0);
+ case XML_CHAR_ENCODING_2022_JP:
+ __xmlErrEncoding(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
+ "encoding not supported %s\n",
+ BAD_CAST "ISO-2022-JP", NULL);
+ break;
+ case XML_CHAR_ENCODING_SHIFT_JIS:
+ __xmlErrEncoding(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
+ "encoding not supported %s\n",
+ BAD_CAST "Shift_JIS", NULL);
+ break;
+ case XML_CHAR_ENCODING_EUC_JP:
+ __xmlErrEncoding(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
+ "encoding not supported %s\n",
+ BAD_CAST "EUC-JP", NULL);
+ break;
+ default:
+ break;
+ }
+ }
+ if (handler == NULL)
+ return(-1);
+ ctxt->charset = XML_CHAR_ENCODING_UTF8;
+ return(xmlSwitchToEncoding(ctxt, handler));
+}
+
+/**
+ * xmlSwitchInputEncoding:
+ * @ctxt: the parser context
+ * @input: the input stream
+ * @handler: the encoding handler
+ *
+ * change the input functions when discovering the character encoding
+ * of a given entity.
+ *
+ * Returns 0 in case of success, -1 otherwise
+ */
+int
+xmlSwitchInputEncoding(xmlParserCtxtPtr ctxt, xmlParserInputPtr input,
+ xmlCharEncodingHandlerPtr handler)
+{
+ int nbchars;
+
+ if (handler == NULL)
+ return (-1);
+ if (input == NULL)
+ return (-1);
+ if (input->buf != NULL) {
+ if (input->buf->encoder != NULL) {
+ /*
+ * Check in case the auto encoding detetection triggered
+ * in already.
+ */
+ if (input->buf->encoder == handler)
+ return (0);
+
+ /*
+ * "UTF-16" can be used for both LE and BE
+ if ((!xmlStrncmp(BAD_CAST input->buf->encoder->name,
+ BAD_CAST "UTF-16", 6)) &&
+ (!xmlStrncmp(BAD_CAST handler->name,
+ BAD_CAST "UTF-16", 6))) {
+ return(0);
+ }
+ */
+
+ /*
+ * Note: this is a bit dangerous, but that's what it
+ * takes to use nearly compatible signature for different
+ * encodings.
+ */
+ xmlCharEncCloseFunc(input->buf->encoder);
+ input->buf->encoder = handler;
+ return (0);
+ }
+ input->buf->encoder = handler;
+
+ /*
+ * Is there already some content down the pipe to convert ?
+ */
+ if ((input->buf->buffer != NULL) && (input->buf->buffer->use > 0)) {
+ int processed;
+ unsigned int use;
+
+ /*
+ * Specific handling of the Byte Order Mark for
+ * UTF-16
+ */
+ if ((handler->name != NULL) &&
+ (!strcmp(handler->name, "UTF-16LE") ||
+ !strcmp(handler->name, "UTF-16")) &&
+ (input->cur[0] == 0xFF) && (input->cur[1] == 0xFE)) {
+ input->cur += 2;
+ }
+ if ((handler->name != NULL) &&
+ (!strcmp(handler->name, "UTF-16BE")) &&
+ (input->cur[0] == 0xFE) && (input->cur[1] == 0xFF)) {
+ input->cur += 2;
+ }
+ /*
+ * Errata on XML-1.0 June 20 2001
+ * Specific handling of the Byte Order Mark for
+ * UTF-8
+ */
+ if ((handler->name != NULL) &&
+ (!strcmp(handler->name, "UTF-8")) &&
+ (input->cur[0] == 0xEF) &&
+ (input->cur[1] == 0xBB) && (input->cur[2] == 0xBF)) {
+ input->cur += 3;
+ }
+
+ /*
+ * Shrink the current input buffer.
+ * Move it as the raw buffer and create a new input buffer
+ */
+ processed = input->cur - input->base;
+ xmlBufferShrink(input->buf->buffer, processed);
+ input->buf->raw = input->buf->buffer;
+ input->buf->buffer = xmlBufferCreate();
+ input->buf->rawconsumed = processed;
+ use = input->buf->raw->use;
+
+ if (ctxt->html) {
+ /*
+ * convert as much as possible of the buffer
+ */
+ nbchars = xmlCharEncInFunc(input->buf->encoder,
+ input->buf->buffer,
+ input->buf->raw);
+ } else {
+ /*
+ * convert just enough to get
+ * '<?xml version="1.0" encoding="xxx"?>'
+ * parsed with the autodetected encoding
+ * into the parser reading buffer.
+ */
+ nbchars = xmlCharEncFirstLine(input->buf->encoder,
+ input->buf->buffer,
+ input->buf->raw);
+ }
+ if (nbchars < 0) {
+ xmlErrInternal(ctxt,
+ "switching encoding: encoder error\n",
+ NULL);
+ return (-1);
+ }
+ input->buf->rawconsumed += use - input->buf->raw->use;
+ input->base = input->cur = input->buf->buffer->content;
+ input->end = &input->base[input->buf->buffer->use];
+
+ }
+ return (0);
+ } else if (input->length == 0) {
+ /*
+ * When parsing a static memory array one must know the
+ * size to be able to convert the buffer.
+ */
+ xmlErrInternal(ctxt, "switching encoding : no input\n", NULL);
+ return (-1);
+ }
+ return (0);
+}
+
+/**
+ * xmlSwitchToEncoding:
+ * @ctxt: the parser context
+ * @handler: the encoding handler
+ *
+ * change the input functions when discovering the character encoding
+ * of a given entity.
+ *
+ * Returns 0 in case of success, -1 otherwise
+ */
+int
+xmlSwitchToEncoding(xmlParserCtxtPtr ctxt, xmlCharEncodingHandlerPtr handler)
+{
+ int ret = 0;
+
+ if (handler != NULL) {
+ if (ctxt->input != NULL) {
+ ret = xmlSwitchInputEncoding(ctxt, ctxt->input, handler);
+ } else {
+ xmlErrInternal(ctxt, "xmlSwitchToEncoding : no input\n",
+ NULL);
+ return(-1);
+ }
+ /*
+ * The parsing is now done in UTF8 natively
+ */
+ ctxt->charset = XML_CHAR_ENCODING_UTF8;
+ } else
+ return(-1);
+ return(ret);
+}
+
+/************************************************************************
+ * *
+ * Commodity functions to handle entities processing *
+ * *
+ ************************************************************************/
+
+/**
+ * xmlFreeInputStream:
+ * @input: an xmlParserInputPtr
+ *
+ * Free up an input stream.
+ */
+void
+xmlFreeInputStream(xmlParserInputPtr input) {
+ if (input == NULL) return;
+
+ if (input->filename != NULL) xmlFree((char *) input->filename);
+ if (input->directory != NULL) xmlFree((char *) input->directory);
+ if (input->encoding != NULL) xmlFree((char *) input->encoding);
+ if (input->version != NULL) xmlFree((char *) input->version);
+ if ((input->free != NULL) && (input->base != NULL))
+ input->free((xmlChar *) input->base);
+ if (input->buf != NULL)
+ xmlFreeParserInputBuffer(input->buf);
+ xmlFree(input);
+}
+
+/**
+ * xmlNewInputStream:
+ * @ctxt: an XML parser context
+ *
+ * Create a new input stream structure
+ * Returns the new input stream or NULL
+ */
+xmlParserInputPtr
+xmlNewInputStream(xmlParserCtxtPtr ctxt) {
+ xmlParserInputPtr input;
+ static int id = 0;
+
+ input = (xmlParserInputPtr) xmlMalloc(sizeof(xmlParserInput));
+ if (input == NULL) {
+ xmlErrMemory(ctxt, "couldn't allocate a new input stream\n");
+ return(NULL);
+ }
+ memset(input, 0, sizeof(xmlParserInput));
+ input->line = 1;
+ input->col = 1;
+ input->standalone = -1;
+ /*
+ * we don't care about thread reentrancy unicity for a single
+ * parser context (and hence thread) is sufficient.
+ */
+ input->id = id++;
+ return(input);
+}
+
+/**
+ * xmlNewIOInputStream:
+ * @ctxt: an XML parser context
+ * @input: an I/O Input
+ * @enc: the charset encoding if known
+ *
+ * Create a new input stream structure encapsulating the @input into
+ * a stream suitable for the parser.
+ *
+ * Returns the new input stream or NULL
+ */
+xmlParserInputPtr
+xmlNewIOInputStream(xmlParserCtxtPtr ctxt, xmlParserInputBufferPtr input,
+ xmlCharEncoding enc) {
+ xmlParserInputPtr inputStream;
+
+ if (input == NULL) return(NULL);
+ if (xmlParserDebugEntities)
+ xmlGenericError(xmlGenericErrorContext, "new input from I/O\n");
+ inputStream = xmlNewInputStream(ctxt);
+ if (inputStream == NULL) {
+ return(NULL);
+ }
+ inputStream->filename = NULL;
+ inputStream->buf = input;
+ inputStream->base = inputStream->buf->buffer->content;
+ inputStream->cur = inputStream->buf->buffer->content;
+ inputStream->end = &inputStream->base[inputStream->buf->buffer->use];
+ if (enc != XML_CHAR_ENCODING_NONE) {
+ xmlSwitchEncoding(ctxt, enc);
+ }
+
+ return(inputStream);
+}
+
+/**
+ * xmlNewEntityInputStream:
+ * @ctxt: an XML parser context
+ * @entity: an Entity pointer
+ *
+ * Create a new input stream based on an xmlEntityPtr
+ *
+ * Returns the new input stream or NULL
+ */
+xmlParserInputPtr
+xmlNewEntityInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
+ xmlParserInputPtr input;
+
+ if (entity == NULL) {
+ xmlErrInternal(ctxt, "xmlNewEntityInputStream entity = NULL\n",
+ NULL);
+ return(NULL);
+ }
+ if (xmlParserDebugEntities)
+ xmlGenericError(xmlGenericErrorContext,
+ "new input from entity: %s\n", entity->name);
+ if (entity->content == NULL) {
+ switch (entity->etype) {
+ case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
+ xmlErrInternal(ctxt, "Cannot parse entity %s\n",
+ entity->name);
+ break;
+ case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
+ case XML_EXTERNAL_PARAMETER_ENTITY:
+ return(xmlLoadExternalEntity((char *) entity->URI,
+ (char *) entity->ExternalID, ctxt));
+ case XML_INTERNAL_GENERAL_ENTITY:
+ xmlErrInternal(ctxt,
+ "Internal entity %s without content !\n",
+ entity->name);
+ break;
+ case XML_INTERNAL_PARAMETER_ENTITY:
+ xmlErrInternal(ctxt,
+ "Internal parameter entity %s without content !\n",
+ entity->name);
+ break;
+ case XML_INTERNAL_PREDEFINED_ENTITY:
+ xmlErrInternal(ctxt,
+ "Predefined entity %s without content !\n",
+ entity->name);
+ break;
+ }
+ return(NULL);
+ }
+ input = xmlNewInputStream(ctxt);
+ if (input == NULL) {
+ return(NULL);
+ }
+ input->filename = (char *) entity->URI;
+ input->base = entity->content;
+ input->cur = entity->content;
+ input->length = entity->length;
+ input->end = &entity->content[input->length];
+ return(input);
+}
+
+/**
+ * xmlNewStringInputStream:
+ * @ctxt: an XML parser context
+ * @buffer: an memory buffer
+ *
+ * Create a new input stream based on a memory buffer.
+ * Returns the new input stream
+ */
+xmlParserInputPtr
+xmlNewStringInputStream(xmlParserCtxtPtr ctxt, const xmlChar *buffer) {
+ xmlParserInputPtr input;
+
+ if (buffer == NULL) {
+ xmlErrInternal(ctxt, "xmlNewStringInputStream string = NULL\n",
+ NULL);
+ return(NULL);
+ }
+ if (xmlParserDebugEntities)
+ xmlGenericError(xmlGenericErrorContext,
+ "new fixed input: %.30s\n", buffer);
+ input = xmlNewInputStream(ctxt);
+ if (input == NULL) {
+ xmlErrMemory(ctxt, "couldn't allocate a new input stream\n");
+ return(NULL);
+ }
+ input->base = buffer;
+ input->cur = buffer;
+ input->length = xmlStrlen(buffer);
+ input->end = &buffer[input->length];
+ return(input);
+}
+
+/**
+ * xmlNewInputFromFile:
+ * @ctxt: an XML parser context
+ * @filename: the filename to use as entity
+ *
+ * Create a new input stream based on a file or an URL.
+ *
+ * Returns the new input stream or NULL in case of error
+ */
+xmlParserInputPtr
+xmlNewInputFromFile(xmlParserCtxtPtr ctxt, const char *filename) {
+ xmlParserInputBufferPtr buf;
+ xmlParserInputPtr inputStream;
+ char *directory = NULL;
+ xmlChar *URI = NULL;
+
+ if (xmlParserDebugEntities)
+ xmlGenericError(xmlGenericErrorContext,
+ "new input from file: %s\n", filename);
+ if (ctxt == NULL) return(NULL);
+ buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
+ if (buf == NULL) {
+ if (filename == NULL)
+ __xmlLoaderErr(ctxt,
+ "failed to load external entity: NULL filename \n",
+ NULL);
+ else
+ __xmlLoaderErr(ctxt, "failed to load external entity \"%s\"\n",
+ (const char *) filename);
+ return(NULL);
+ }
+
+ inputStream = xmlNewInputStream(ctxt);
+ if (inputStream == NULL)
+ return(NULL);
+
+ inputStream->buf = buf;
+ inputStream = xmlCheckHTTPInput(ctxt, inputStream);
+ if (inputStream == NULL)
+ return(NULL);
+
+ if (inputStream->filename == NULL)
+ URI = xmlStrdup((xmlChar *) filename);
+ else
+ URI = xmlStrdup((xmlChar *) inputStream->filename);
+ directory = xmlParserGetDirectory((const char *) URI);
+ if (inputStream->filename != NULL) xmlFree((char *)inputStream->filename);
+ inputStream->filename = (char *) xmlCanonicPath((const xmlChar *) URI);
+ if (URI != NULL) xmlFree((char *) URI);
+ inputStream->directory = directory;
+
+ inputStream->base = inputStream->buf->buffer->content;
+ inputStream->cur = inputStream->buf->buffer->content;
+ inputStream->end = &inputStream->base[inputStream->buf->buffer->use];
+ if ((ctxt->directory == NULL) && (directory != NULL))
+ ctxt->directory = (char *) xmlStrdup((const xmlChar *) directory);
+ return(inputStream);
+}
+
+/************************************************************************
+ * *
+ * Commodity functions to handle parser contexts *
+ * *
+ ************************************************************************/
+
+/**
+ * xmlInitParserCtxt:
+ * @ctxt: an XML parser context
+ *
+ * Initialize a parser context
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+
+int
+xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
+{
+ xmlParserInputPtr input;
+
+ if(ctxt==NULL) {
+ xmlErrInternal(NULL, "Got NULL parser context\n", NULL);
+ return(-1);
+ }
+
+ xmlDefaultSAXHandlerInit();
+
+ if (ctxt->dict == NULL)
+ ctxt->dict = xmlDictCreate();
+ if (ctxt->dict == NULL) {
+ xmlErrMemory(NULL, "cannot initialize parser context\n");
+ return(-1);
+ }
+ if (ctxt->sax == NULL)
+ ctxt->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
+ if (ctxt->sax == NULL) {
+ xmlErrMemory(NULL, "cannot initialize parser context\n");
+ return(-1);
+ }
+ else
+ xmlSAXVersion(ctxt->sax, 2);
+
+ ctxt->maxatts = 0;
+ ctxt->atts = NULL;
+ /* Allocate the Input stack */
+ if (ctxt->inputTab == NULL) {
+ ctxt->inputTab = (xmlParserInputPtr *)
+ xmlMalloc(5 * sizeof(xmlParserInputPtr));
+ ctxt->inputMax = 5;
+ }
+ if (ctxt->inputTab == NULL) {
+ xmlErrMemory(NULL, "cannot initialize parser context\n");
+ ctxt->inputNr = 0;
+ ctxt->inputMax = 0;
+ ctxt->input = NULL;
+ return(-1);
+ }
+ while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */
+ xmlFreeInputStream(input);
+ }
+ ctxt->inputNr = 0;
+ ctxt->input = NULL;
+
+ ctxt->version = NULL;
+ ctxt->encoding = NULL;
+ ctxt->standalone = -1;
+ ctxt->hasExternalSubset = 0;
+ ctxt->hasPErefs = 0;
+ ctxt->html = 0;
+ ctxt->external = 0;
+ ctxt->instate = XML_PARSER_START;
+ ctxt->token = 0;
+ ctxt->directory = NULL;
+
+ /* Allocate the Node stack */
+ if (ctxt->nodeTab == NULL) {
+ ctxt->nodeTab = (xmlNodePtr *) xmlMalloc(10 * sizeof(xmlNodePtr));
+ ctxt->nodeMax = 10;
+ }
+ if (ctxt->nodeTab == NULL) {
+ xmlErrMemory(NULL, "cannot initialize parser context\n");
+ ctxt->nodeNr = 0;
+ ctxt->nodeMax = 0;
+ ctxt->node = NULL;
+ ctxt->inputNr = 0;
+ ctxt->inputMax = 0;
+ ctxt->input = NULL;
+ return(-1);
+ }
+ ctxt->nodeNr = 0;
+ ctxt->node = NULL;
+
+ /* Allocate the Name stack */
+ if (ctxt->nameTab == NULL) {
+ ctxt->nameTab = (const xmlChar **) xmlMalloc(10 * sizeof(xmlChar *));
+ ctxt->nameMax = 10;
+ }
+ if (ctxt->nameTab == NULL) {
+ xmlErrMemory(NULL, "cannot initialize parser context\n");
+ ctxt->nodeNr = 0;
+ ctxt->nodeMax = 0;
+ ctxt->node = NULL;
+ ctxt->inputNr = 0;
+ ctxt->inputMax = 0;
+ ctxt->input = NULL;
+ ctxt->nameNr = 0;
+ ctxt->nameMax = 0;
+ ctxt->name = NULL;
+ return(-1);
+ }
+ ctxt->nameNr = 0;
+ ctxt->name = NULL;
+
+ /* Allocate the space stack */
+ if (ctxt->spaceTab == NULL) {
+ ctxt->spaceTab = (int *) xmlMalloc(10 * sizeof(int));
+ ctxt->spaceMax = 10;
+ }
+ if (ctxt->spaceTab == NULL) {
+ xmlErrMemory(NULL, "cannot initialize parser context\n");
+ ctxt->nodeNr = 0;
+ ctxt->nodeMax = 0;
+ ctxt->node = NULL;
+ ctxt->inputNr = 0;
+ ctxt->inputMax = 0;
+ ctxt->input = NULL;
+ ctxt->nameNr = 0;
+ ctxt->nameMax = 0;
+ ctxt->name = NULL;
+ ctxt->spaceNr = 0;
+ ctxt->spaceMax = 0;
+ ctxt->space = NULL;
+ return(-1);
+ }
+ ctxt->spaceNr = 1;
+ ctxt->spaceMax = 10;
+ ctxt->spaceTab[0] = -1;
+ ctxt->space = &ctxt->spaceTab[0];
+ ctxt->userData = ctxt;
+ ctxt->myDoc = NULL;
+ ctxt->wellFormed = 1;
+ ctxt->nsWellFormed = 1;
+ ctxt->valid = 1;
+ ctxt->loadsubset = xmlLoadExtDtdDefaultValue;
+ ctxt->validate = xmlDoValidityCheckingDefaultValue;
+ ctxt->pedantic = xmlPedanticParserDefaultValue;
+ ctxt->linenumbers = xmlLineNumbersDefaultValue;
+ ctxt->keepBlanks = xmlKeepBlanksDefaultValue;
+ if (ctxt->keepBlanks == 0)
+ ctxt->sax->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
+
+ ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_0;
+ ctxt->vctxt.userData = ctxt;
+ ctxt->vctxt.error = xmlParserValidityError;
+ ctxt->vctxt.warning = xmlParserValidityWarning;
+ if (ctxt->validate) {
+ if (xmlGetWarningsDefaultValue == 0)
+ ctxt->vctxt.warning = NULL;
+ else
+ ctxt->vctxt.warning = xmlParserValidityWarning;
+ ctxt->vctxt.nodeMax = 0;
+ }
+ ctxt->replaceEntities = xmlSubstituteEntitiesDefaultValue;
+ 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);
+ return(0);
+}
+
+/**
+ * xmlFreeParserCtxt:
+ * @ctxt: an XML parser context
+ *
+ * Free all the memory used by a parser context. However the parsed
+ * document in ctxt->myDoc is not freed.
+ */
+
+void
+xmlFreeParserCtxt(xmlParserCtxtPtr ctxt)
+{
+ xmlParserInputPtr input;
+
+ if (ctxt == NULL) return;
+
+ while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */
+ xmlFreeInputStream(input);
+ }
+ if (ctxt->spaceTab != NULL) xmlFree(ctxt->spaceTab);
+ if (ctxt->nameTab != NULL) xmlFree((xmlChar * *)ctxt->nameTab);
+ if (ctxt->nodeTab != NULL) xmlFree(ctxt->nodeTab);
+ if (ctxt->inputTab != NULL) xmlFree(ctxt->inputTab);
+ if (ctxt->version != NULL) xmlFree((char *) ctxt->version);
+ if (ctxt->encoding != NULL) xmlFree((char *) ctxt->encoding);
+ if (ctxt->extSubURI != NULL) xmlFree((char *) ctxt->extSubURI);
+ if (ctxt->extSubSystem != NULL) xmlFree((char *) ctxt->extSubSystem);
+#ifdef LIBXML_SAX1_ENABLED
+ if ((ctxt->sax != NULL) &&
+ (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler))
+#else
+ if (ctxt->sax != NULL)
+#endif /* LIBXML_SAX1_ENABLED */
+ xmlFree(ctxt->sax);
+ if (ctxt->directory != NULL) xmlFree((char *) ctxt->directory);
+ if (ctxt->vctxt.nodeTab != NULL) xmlFree(ctxt->vctxt.nodeTab);
+ if (ctxt->atts != NULL) xmlFree((xmlChar * *)ctxt->atts);
+ if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
+ if (ctxt->nsTab != NULL) xmlFree((char *) ctxt->nsTab);
+ if (ctxt->pushTab != NULL) xmlFree(ctxt->pushTab);
+ if (ctxt->attallocs != NULL) xmlFree(ctxt->attallocs);
+ if (ctxt->attsDefault != NULL)
+ xmlHashFree(ctxt->attsDefault, (xmlHashDeallocator) xmlFree);
+ if (ctxt->attsSpecial != NULL)
+ xmlHashFree(ctxt->attsSpecial, NULL);
+ if (ctxt->freeElems != NULL) {
+ xmlNodePtr cur, next;
+
+ cur = ctxt->freeElems;
+ while (cur != NULL) {
+ next = cur->next;
+ xmlFree(cur);
+ cur = next;
+ }
+ }
+ if (ctxt->freeAttrs != NULL) {
+ xmlAttrPtr cur, next;
+
+ cur = ctxt->freeAttrs;
+ while (cur != NULL) {
+ next = cur->next;
+ xmlFree(cur);
+ cur = next;
+ }
+ }
+ /*
+ * cleanup the error strings
+ */
+ if (ctxt->lastError.message != NULL)
+ xmlFree(ctxt->lastError.message);
+ if (ctxt->lastError.file != NULL)
+ xmlFree(ctxt->lastError.file);
+ if (ctxt->lastError.str1 != NULL)
+ xmlFree(ctxt->lastError.str1);
+ if (ctxt->lastError.str2 != NULL)
+ xmlFree(ctxt->lastError.str2);
+ if (ctxt->lastError.str3 != NULL)
+ xmlFree(ctxt->lastError.str3);
+
+#ifdef LIBXML_CATALOG_ENABLED
+ if (ctxt->catalogs != NULL)
+ xmlCatalogFreeLocal(ctxt->catalogs);
+#endif
+ xmlFree(ctxt);
+}
+
+/**
+ * xmlNewParserCtxt:
+ *
+ * Allocate and initialize a new parser context.
+ *
+ * Returns the xmlParserCtxtPtr or NULL
+ */
+
+xmlParserCtxtPtr
+xmlNewParserCtxt(void)
+{
+ xmlParserCtxtPtr ctxt;
+
+ ctxt = (xmlParserCtxtPtr) xmlMalloc(sizeof(xmlParserCtxt));
+ if (ctxt == NULL) {
+ xmlErrMemory(NULL, "cannot allocate parser context\n");
+ return(NULL);
+ }
+ memset(ctxt, 0, sizeof(xmlParserCtxt));
+ if (xmlInitParserCtxt(ctxt) < 0) {
+ xmlFreeParserCtxt(ctxt);
+ return(NULL);
+ }
+ return(ctxt);
+}
+
+/************************************************************************
+ * *
+ * Handling of node informations *
+ * *
+ ************************************************************************/
+
+/**
+ * xmlClearParserCtxt:
+ * @ctxt: an XML parser context
+ *
+ * Clear (release owned resources) and reinitialize a parser context
+ */
+
+void
+xmlClearParserCtxt(xmlParserCtxtPtr ctxt)
+{
+ if (ctxt==NULL)
+ return;
+ xmlClearNodeInfoSeq(&ctxt->node_seq);
+ xmlCtxtReset(ctxt);
+}
+
+
+/**
+ * xmlParserFindNodeInfo:
+ * @ctx: an XML parser context
+ * @node: an XML node within the tree
+ *
+ * Find the parser node info struct for a given node
+ *
+ * Returns an xmlParserNodeInfo block pointer or NULL
+ */
+const xmlParserNodeInfo *
+xmlParserFindNodeInfo(const xmlParserCtxtPtr ctx, const xmlNodePtr node)
+{
+ unsigned long pos;
+
+ if ((ctx == NULL) || (node == NULL))
+ return (NULL);
+ /* Find position where node should be at */
+ pos = xmlParserFindNodeInfoIndex(&ctx->node_seq, node);
+ if (pos < ctx->node_seq.length
+ && ctx->node_seq.buffer[pos].node == node)
+ return &ctx->node_seq.buffer[pos];
+ else
+ return NULL;
+}
+
+
+/**
+ * xmlInitNodeInfoSeq:
+ * @seq: a node info sequence pointer
+ *
+ * -- Initialize (set to initial state) node info sequence
+ */
+void
+xmlInitNodeInfoSeq(xmlParserNodeInfoSeqPtr seq)
+{
+ if (seq == NULL)
+ return;
+ seq->length = 0;
+ seq->maximum = 0;
+ seq->buffer = NULL;
+}
+
+/**
+ * xmlClearNodeInfoSeq:
+ * @seq: a node info sequence pointer
+ *
+ * -- Clear (release memory and reinitialize) node
+ * info sequence
+ */
+void
+xmlClearNodeInfoSeq(xmlParserNodeInfoSeqPtr seq)
+{
+ if (seq == NULL)
+ return;
+ if (seq->buffer != NULL)
+ xmlFree(seq->buffer);
+ xmlInitNodeInfoSeq(seq);
+}
+
+/**
+ * xmlParserFindNodeInfoIndex:
+ * @seq: a node info sequence pointer
+ * @node: an XML node pointer
+ *
+ *
+ * xmlParserFindNodeInfoIndex : Find the index that the info record for
+ * the given node is or should be at in a sorted sequence
+ *
+ * Returns a long indicating the position of the record
+ */
+unsigned long
+xmlParserFindNodeInfoIndex(const xmlParserNodeInfoSeqPtr seq,
+ const xmlNodePtr node)
+{
+ unsigned long upper, lower, middle;
+ int found = 0;
+
+ if ((seq == NULL) || (node == NULL))
+ return ((unsigned long) -1);
+
+ /* Do a binary search for the key */
+ lower = 1;
+ upper = seq->length;
+ middle = 0;
+ while (lower <= upper && !found) {
+ middle = lower + (upper - lower) / 2;
+ if (node == seq->buffer[middle - 1].node)
+ found = 1;
+ else if (node < seq->buffer[middle - 1].node)
+ upper = middle - 1;
+ else
+ lower = middle + 1;
+ }
+
+ /* Return position */
+ if (middle == 0 || seq->buffer[middle - 1].node < node)
+ return middle;
+ else
+ return middle - 1;
+}
+
+
+/**
+ * xmlParserAddNodeInfo:
+ * @ctxt: an XML parser context
+ * @info: a node info sequence pointer
+ *
+ * Insert node info record into the sorted sequence
+ */
+void
+xmlParserAddNodeInfo(xmlParserCtxtPtr ctxt,
+ const xmlParserNodeInfoPtr info)
+{
+ unsigned long pos;
+
+ if ((ctxt == NULL) || (info == NULL)) return;
+
+ /* Find pos and check to see if node is already in the sequence */
+ pos = xmlParserFindNodeInfoIndex(&ctxt->node_seq, (xmlNodePtr)
+ info->node);
+
+ if ((pos < ctxt->node_seq.length) &&
+ (ctxt->node_seq.buffer != NULL) &&
+ (ctxt->node_seq.buffer[pos].node == info->node)) {
+ ctxt->node_seq.buffer[pos] = *info;
+ }
+
+ /* Otherwise, we need to add new node to buffer */
+ else {
+ if (ctxt->node_seq.length + 1 > ctxt->node_seq.maximum) {
+ xmlParserNodeInfo *tmp_buffer;
+ unsigned int byte_size;
+
+ if (ctxt->node_seq.maximum == 0)
+ ctxt->node_seq.maximum = 2;
+ byte_size = (sizeof(*ctxt->node_seq.buffer) *
+ (2 * ctxt->node_seq.maximum));
+
+ if (ctxt->node_seq.buffer == NULL)
+ tmp_buffer = (xmlParserNodeInfo *) xmlMalloc(byte_size);
+ else
+ tmp_buffer =
+ (xmlParserNodeInfo *) xmlRealloc(ctxt->node_seq.buffer,
+ byte_size);
+
+ if (tmp_buffer == NULL) {
+ xmlErrMemory(ctxt, "failed to allocate buffer\n");
+ return;
+ }
+ ctxt->node_seq.buffer = tmp_buffer;
+ ctxt->node_seq.maximum *= 2;
+ }
+
+ /* If position is not at end, move elements out of the way */
+ if (pos != ctxt->node_seq.length) {
+ unsigned long i;
+
+ for (i = ctxt->node_seq.length; i > pos; i--)
+ ctxt->node_seq.buffer[i] = ctxt->node_seq.buffer[i - 1];
+ }
+
+ /* Copy element and increase length */
+ ctxt->node_seq.buffer[pos] = *info;
+ ctxt->node_seq.length++;
+ }
+}
+
+/************************************************************************
+ * *
+ * Defaults settings *
+ * *
+ ************************************************************************/
+/**
+ * xmlPedanticParserDefault:
+ * @val: int 0 or 1
+ *
+ * Set and return the previous value for enabling pedantic warnings.
+ *
+ * Returns the last value for 0 for no substitution, 1 for substitution.
+ */
+
+int
+xmlPedanticParserDefault(int val) {
+ int old = xmlPedanticParserDefaultValue;
+
+ xmlPedanticParserDefaultValue = val;
+ return(old);
+}
+
+/**
+ * xmlLineNumbersDefault:
+ * @val: int 0 or 1
+ *
+ * Set and return the previous value for enabling line numbers in elements
+ * contents. This may break on old application and is turned off by default.
+ *
+ * Returns the last value for 0 for no substitution, 1 for substitution.
+ */
+
+int
+xmlLineNumbersDefault(int val) {
+ int old = xmlLineNumbersDefaultValue;
+
+ xmlLineNumbersDefaultValue = val;
+ return(old);
+}
+
+/**
+ * xmlSubstituteEntitiesDefault:
+ * @val: int 0 or 1
+ *
+ * Set and return the previous value for default entity support.
+ * Initially the parser always keep entity references instead of substituting
+ * entity values in the output. This function has to be used to change the
+ * default parser behavior
+ * SAX::substituteEntities() has to be used for changing that on a file by
+ * file basis.
+ *
+ * Returns the last value for 0 for no substitution, 1 for substitution.
+ */
+
+int
+xmlSubstituteEntitiesDefault(int val) {
+ int old = xmlSubstituteEntitiesDefaultValue;
+
+ xmlSubstituteEntitiesDefaultValue = val;
+ return(old);
+}
+
+/**
+ * xmlKeepBlanksDefault:
+ * @val: int 0 or 1
+ *
+ * Set and return the previous value for default blanks text nodes support.
+ * The 1.x version of the parser used an heuristic to try to detect
+ * ignorable white spaces. As a result the SAX callback was generating
+ * xmlSAX2IgnorableWhitespace() callbacks instead of characters() one, and when
+ * using the DOM output text nodes containing those blanks were not generated.
+ * The 2.x and later version will switch to the XML standard way and
+ * ignorableWhitespace() are only generated when running the parser in
+ * validating mode and when the current element doesn't allow CDATA or
+ * mixed content.
+ * This function is provided as a way to force the standard behavior
+ * on 1.X libs and to switch back to the old mode for compatibility when
+ * running 1.X client code on 2.X . Upgrade of 1.X code should be done
+ * by using xmlIsBlankNode() commodity function to detect the "empty"
+ * nodes generated.
+ * This value also affect autogeneration of indentation when saving code
+ * if blanks sections are kept, indentation is not generated.
+ *
+ * Returns the last value for 0 for no substitution, 1 for substitution.
+ */
+
+int
+xmlKeepBlanksDefault(int val) {
+ int old = xmlKeepBlanksDefaultValue;
+
+ xmlKeepBlanksDefaultValue = val;
+ xmlIndentTreeOutput = !val;
+ return(old);
+}
+
+#define bottom_parserInternals
+#include "elfgcchack.h"
diff --git a/gettext-tools/gnulib-lib/libxml/parserInternals.in.h b/gettext-tools/gnulib-lib/libxml/parserInternals.in.h
new file mode 100644
index 0000000..7ac0ce6
--- /dev/null
+++ b/gettext-tools/gnulib-lib/libxml/parserInternals.in.h
@@ -0,0 +1,602 @@
+/*
+ * Summary: internals routines exported by the parser.
+ * Description: this module exports a number of internal parsing routines
+ * they are not really all intended for applications but
+ * can prove useful doing low level processing.
+ *
+ * Copy: See Copyright for the status of this software.
+ *
+ * Author: Daniel Veillard
+ */
+
+#ifndef __XML_PARSER_INTERNALS_H__
+#define __XML_PARSER_INTERNALS_H__
+
+#include <libxml/xmlversion.h>
+#include <libxml/parser.h>
+#include <libxml/HTMLparser.h>
+#include <libxml/chvalid.h>
+
+#ifdef __cplusplus
+extern "C" {
+#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.
+ */
+XMLPUBVAR unsigned int xmlParserMaxDepth;
+
+ /**
+ * XML_MAX_NAMELEN:
+ *
+ * Identifiers can be longer, but this will be more costly
+ * at runtime.
+ */
+#define XML_MAX_NAMELEN 100
+
+/**
+ * INPUT_CHUNK:
+ *
+ * The parser tries to always have that amount of input ready.
+ * One of the point is providing context when reporting errors.
+ */
+#define INPUT_CHUNK 250
+
+/************************************************************************
+ * *
+ * UNICODE version of the macros. *
+ * *
+ ************************************************************************/
+/**
+ * IS_BYTE_CHAR:
+ * @c: an byte value (int)
+ *
+ * Macro to check the following production in the XML spec:
+ *
+ * [2] Char ::= #x9 | #xA | #xD | [#x20...]
+ * any byte character in the accepted range
+ */
+#define IS_BYTE_CHAR(c) xmlIsChar_ch(c)
+
+/**
+ * IS_CHAR:
+ * @c: an UNICODE value (int)
+ *
+ * Macro to check the following production in the XML spec:
+ *
+ * [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD]
+ * | [#x10000-#x10FFFF]
+ * any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
+ */
+#define IS_CHAR(c) xmlIsCharQ(c)
+
+/**
+ * IS_CHAR_CH:
+ * @c: an xmlChar (usually an unsigned char)
+ *
+ * Behaves like IS_CHAR on single-byte value
+ */
+#define IS_CHAR_CH(c) xmlIsChar_ch(c)
+
+/**
+ * IS_BLANK:
+ * @c: an UNICODE value (int)
+ *
+ * Macro to check the following production in the XML spec:
+ *
+ * [3] S ::= (#x20 | #x9 | #xD | #xA)+
+ */
+#define IS_BLANK(c) xmlIsBlankQ(c)
+
+/**
+ * IS_BLANK_CH:
+ * @c: an xmlChar value (normally unsigned char)
+ *
+ * Behaviour same as IS_BLANK
+ */
+#define IS_BLANK_CH(c) xmlIsBlank_ch(c)
+
+/**
+ * IS_BASECHAR:
+ * @c: an UNICODE value (int)
+ *
+ * Macro to check the following production in the XML spec:
+ *
+ * [85] BaseChar ::= ... long list see REC ...
+ */
+#define IS_BASECHAR(c) xmlIsBaseCharQ(c)
+
+/**
+ * IS_DIGIT:
+ * @c: an UNICODE value (int)
+ *
+ * Macro to check the following production in the XML spec:
+ *
+ * [88] Digit ::= ... long list see REC ...
+ */
+#define IS_DIGIT(c) xmlIsDigitQ(c)
+
+/**
+ * IS_DIGIT_CH:
+ * @c: an xmlChar value (usually an unsigned char)
+ *
+ * Behaves like IS_DIGIT but with a single byte argument
+ */
+#define IS_DIGIT_CH(c) xmlIsDigit_ch(c)
+
+/**
+ * IS_COMBINING:
+ * @c: an UNICODE value (int)
+ *
+ * Macro to check the following production in the XML spec:
+ *
+ * [87] CombiningChar ::= ... long list see REC ...
+ */
+#define IS_COMBINING(c) xmlIsCombiningQ(c)
+
+/**
+ * IS_COMBINING_CH:
+ * @c: an xmlChar (usually an unsigned char)
+ *
+ * Always false (all combining chars > 0xff)
+ */
+#define IS_COMBINING_CH(c) 0
+
+/**
+ * IS_EXTENDER:
+ * @c: an UNICODE value (int)
+ *
+ * Macro to check the following production in the XML spec:
+ *
+ *
+ * [89] Extender ::= #x00B7 | #x02D0 | #x02D1 | #x0387 | #x0640 |
+ * #x0E46 | #x0EC6 | #x3005 | [#x3031-#x3035] |
+ * [#x309D-#x309E] | [#x30FC-#x30FE]
+ */
+#define IS_EXTENDER(c) xmlIsExtenderQ(c)
+
+/**
+ * IS_EXTENDER_CH:
+ * @c: an xmlChar value (usually an unsigned char)
+ *
+ * Behaves like IS_EXTENDER but with a single-byte argument
+ */
+#define IS_EXTENDER_CH(c) xmlIsExtender_ch(c)
+
+/**
+ * IS_IDEOGRAPHIC:
+ * @c: an UNICODE value (int)
+ *
+ * Macro to check the following production in the XML spec:
+ *
+ *
+ * [86] Ideographic ::= [#x4E00-#x9FA5] | #x3007 | [#x3021-#x3029]
+ */
+#define IS_IDEOGRAPHIC(c) xmlIsIdeographicQ(c)
+
+/**
+ * IS_LETTER:
+ * @c: an UNICODE value (int)
+ *
+ * Macro to check the following production in the XML spec:
+ *
+ *
+ * [84] Letter ::= BaseChar | Ideographic
+ */
+#define IS_LETTER(c) (IS_BASECHAR(c) || IS_IDEOGRAPHIC(c))
+
+/**
+ * IS_LETTER_CH:
+ * @c: an xmlChar value (normally unsigned char)
+ *
+ * Macro behaves like IS_LETTER, but only check base chars
+ *
+ */
+#define IS_LETTER_CH(c) xmlIsBaseChar_ch(c)
+
+/**
+ * IS_ASCII_LETTER:
+ * @c: an xmlChar value
+ *
+ * Macro to check [a-zA-Z]
+ *
+ */
+#define IS_ASCII_LETTER(c) (((0x41 <= (c)) && ((c) <= 0x5a)) || \
+ ((0x61 <= (c)) && ((c) <= 0x7a)))
+
+/**
+ * IS_ASCII_DIGIT:
+ * @c: an xmlChar value
+ *
+ * Macro to check [0-9]
+ *
+ */
+#define IS_ASCII_DIGIT(c) ((0x30 <= (c)) && ((c) <= 0x39))
+
+/**
+ * IS_PUBIDCHAR:
+ * @c: an UNICODE value (int)
+ *
+ * Macro to check the following production in the XML spec:
+ *
+ *
+ * [13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
+ */
+#define IS_PUBIDCHAR(c) xmlIsPubidCharQ(c)
+
+/**
+ * IS_PUBIDCHAR_CH:
+ * @c: an xmlChar value (normally unsigned char)
+ *
+ * Same as IS_PUBIDCHAR but for single-byte value
+ */
+#define IS_PUBIDCHAR_CH(c) xmlIsPubidChar_ch(c)
+
+/**
+ * SKIP_EOL:
+ * @p: and UTF8 string pointer
+ *
+ * Skips the end of line chars.
+ */
+#define SKIP_EOL(p) \
+ if (*(p) == 0x13) { p++ ; if (*(p) == 0x10) p++; } \
+ if (*(p) == 0x10) { p++ ; if (*(p) == 0x13) p++; }
+
+/**
+ * MOVETO_ENDTAG:
+ * @p: and UTF8 string pointer
+ *
+ * Skips to the next '>' char.
+ */
+#define MOVETO_ENDTAG(p) \
+ while ((*p) && (*(p) != '>')) (p)++
+
+/**
+ * MOVETO_STARTTAG:
+ * @p: and UTF8 string pointer
+ *
+ * Skips to the next '<' char.
+ */
+#define MOVETO_STARTTAG(p) \
+ while ((*p) && (*(p) != '<')) (p)++
+
+/**
+ * Global variables used for predefined strings.
+ */
+XMLPUBVAR const xmlChar xmlStringText[];
+XMLPUBVAR const xmlChar xmlStringTextNoenc[];
+XMLPUBVAR const xmlChar xmlStringComment[];
+
+/*
+ * Function to finish the work of the macros where needed.
+ */
+XMLPUBFUN int XMLCALL xmlIsLetter (int c);
+
+/**
+ * Parser context.
+ */
+XMLPUBFUN xmlParserCtxtPtr XMLCALL
+ xmlCreateFileParserCtxt (const char *filename);
+XMLPUBFUN xmlParserCtxtPtr XMLCALL
+ xmlCreateURLParserCtxt (const char *filename,
+ int options);
+XMLPUBFUN xmlParserCtxtPtr XMLCALL
+ xmlCreateMemoryParserCtxt(const char *buffer,
+ int size);
+XMLPUBFUN xmlParserCtxtPtr XMLCALL
+ xmlCreateEntityParserCtxt(const xmlChar *URL,
+ const xmlChar *ID,
+ const xmlChar *base);
+XMLPUBFUN int XMLCALL
+ xmlSwitchEncoding (xmlParserCtxtPtr ctxt,
+ xmlCharEncoding enc);
+XMLPUBFUN int XMLCALL
+ xmlSwitchToEncoding (xmlParserCtxtPtr ctxt,
+ xmlCharEncodingHandlerPtr handler);
+XMLPUBFUN int XMLCALL
+ xmlSwitchInputEncoding (xmlParserCtxtPtr ctxt,
+ xmlParserInputPtr input,
+ xmlCharEncodingHandlerPtr handler);
+
+#ifdef IN_LIBXML
+/* internal error reporting */
+XMLPUBFUN void XMLCALL
+ __xmlErrEncoding (xmlParserCtxtPtr ctxt,
+ xmlParserErrors xmlerr,
+ const char *msg,
+ const xmlChar * str1,
+ const xmlChar * str2);
+#endif
+
+/**
+ * Input Streams.
+ */
+XMLPUBFUN xmlParserInputPtr XMLCALL
+ xmlNewStringInputStream (xmlParserCtxtPtr ctxt,
+ const xmlChar *buffer);
+XMLPUBFUN xmlParserInputPtr XMLCALL
+ xmlNewEntityInputStream (xmlParserCtxtPtr ctxt,
+ xmlEntityPtr entity);
+XMLPUBFUN void XMLCALL
+ xmlPushInput (xmlParserCtxtPtr ctxt,
+ xmlParserInputPtr input);
+XMLPUBFUN xmlChar XMLCALL
+ xmlPopInput (xmlParserCtxtPtr ctxt);
+XMLPUBFUN void XMLCALL
+ xmlFreeInputStream (xmlParserInputPtr input);
+XMLPUBFUN xmlParserInputPtr XMLCALL
+ xmlNewInputFromFile (xmlParserCtxtPtr ctxt,
+ const char *filename);
+XMLPUBFUN xmlParserInputPtr XMLCALL
+ xmlNewInputStream (xmlParserCtxtPtr ctxt);
+
+/**
+ * Namespaces.
+ */
+XMLPUBFUN xmlChar * XMLCALL
+ xmlSplitQName (xmlParserCtxtPtr ctxt,
+ const xmlChar *name,
+ xmlChar **prefix);
+
+/**
+ * Generic production rules.
+ */
+XMLPUBFUN const xmlChar * XMLCALL
+ xmlParseName (xmlParserCtxtPtr ctxt);
+XMLPUBFUN xmlChar * XMLCALL
+ xmlParseNmtoken (xmlParserCtxtPtr ctxt);
+XMLPUBFUN xmlChar * XMLCALL
+ xmlParseEntityValue (xmlParserCtxtPtr ctxt,
+ xmlChar **orig);
+XMLPUBFUN xmlChar * XMLCALL
+ xmlParseAttValue (xmlParserCtxtPtr ctxt);
+XMLPUBFUN xmlChar * XMLCALL
+ xmlParseSystemLiteral (xmlParserCtxtPtr ctxt);
+XMLPUBFUN xmlChar * XMLCALL
+ xmlParsePubidLiteral (xmlParserCtxtPtr ctxt);
+XMLPUBFUN void XMLCALL
+ xmlParseCharData (xmlParserCtxtPtr ctxt,
+ int cdata);
+XMLPUBFUN xmlChar * XMLCALL
+ xmlParseExternalID (xmlParserCtxtPtr ctxt,
+ xmlChar **publicID,
+ int strict);
+XMLPUBFUN void XMLCALL
+ xmlParseComment (xmlParserCtxtPtr ctxt);
+XMLPUBFUN const xmlChar * XMLCALL
+ xmlParsePITarget (xmlParserCtxtPtr ctxt);
+XMLPUBFUN void XMLCALL
+ xmlParsePI (xmlParserCtxtPtr ctxt);
+XMLPUBFUN void XMLCALL
+ xmlParseNotationDecl (xmlParserCtxtPtr ctxt);
+XMLPUBFUN void XMLCALL
+ xmlParseEntityDecl (xmlParserCtxtPtr ctxt);
+XMLPUBFUN int XMLCALL
+ xmlParseDefaultDecl (xmlParserCtxtPtr ctxt,
+ xmlChar **value);
+XMLPUBFUN xmlEnumerationPtr XMLCALL
+ xmlParseNotationType (xmlParserCtxtPtr ctxt);
+XMLPUBFUN xmlEnumerationPtr XMLCALL
+ xmlParseEnumerationType (xmlParserCtxtPtr ctxt);
+XMLPUBFUN int XMLCALL
+ xmlParseEnumeratedType (xmlParserCtxtPtr ctxt,
+ xmlEnumerationPtr *tree);
+XMLPUBFUN int XMLCALL
+ xmlParseAttributeType (xmlParserCtxtPtr ctxt,
+ xmlEnumerationPtr *tree);
+XMLPUBFUN void XMLCALL
+ xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt);
+XMLPUBFUN xmlElementContentPtr XMLCALL
+ xmlParseElementMixedContentDecl
+ (xmlParserCtxtPtr ctxt,
+ int inputchk);
+XMLPUBFUN xmlElementContentPtr XMLCALL
+ xmlParseElementChildrenContentDecl
+ (xmlParserCtxtPtr ctxt,
+ int inputchk);
+XMLPUBFUN int XMLCALL
+ xmlParseElementContentDecl(xmlParserCtxtPtr ctxt,
+ const xmlChar *name,
+ xmlElementContentPtr *result);
+XMLPUBFUN int XMLCALL
+ xmlParseElementDecl (xmlParserCtxtPtr ctxt);
+XMLPUBFUN void XMLCALL
+ xmlParseMarkupDecl (xmlParserCtxtPtr ctxt);
+XMLPUBFUN int XMLCALL
+ xmlParseCharRef (xmlParserCtxtPtr ctxt);
+XMLPUBFUN xmlEntityPtr XMLCALL
+ xmlParseEntityRef (xmlParserCtxtPtr ctxt);
+XMLPUBFUN void XMLCALL
+ xmlParseReference (xmlParserCtxtPtr ctxt);
+XMLPUBFUN void XMLCALL
+ xmlParsePEReference (xmlParserCtxtPtr ctxt);
+XMLPUBFUN void XMLCALL
+ xmlParseDocTypeDecl (xmlParserCtxtPtr ctxt);
+#ifdef LIBXML_SAX1_ENABLED
+XMLPUBFUN const xmlChar * XMLCALL
+ xmlParseAttribute (xmlParserCtxtPtr ctxt,
+ xmlChar **value);
+XMLPUBFUN const xmlChar * XMLCALL
+ xmlParseStartTag (xmlParserCtxtPtr ctxt);
+XMLPUBFUN void XMLCALL
+ xmlParseEndTag (xmlParserCtxtPtr ctxt);
+#endif /* LIBXML_SAX1_ENABLED */
+XMLPUBFUN void XMLCALL
+ xmlParseCDSect (xmlParserCtxtPtr ctxt);
+XMLPUBFUN void XMLCALL
+ xmlParseContent (xmlParserCtxtPtr ctxt);
+XMLPUBFUN void XMLCALL
+ xmlParseElement (xmlParserCtxtPtr ctxt);
+XMLPUBFUN xmlChar * XMLCALL
+ xmlParseVersionNum (xmlParserCtxtPtr ctxt);
+XMLPUBFUN xmlChar * XMLCALL
+ xmlParseVersionInfo (xmlParserCtxtPtr ctxt);
+XMLPUBFUN xmlChar * XMLCALL
+ xmlParseEncName (xmlParserCtxtPtr ctxt);
+XMLPUBFUN const xmlChar * XMLCALL
+ xmlParseEncodingDecl (xmlParserCtxtPtr ctxt);
+XMLPUBFUN int XMLCALL
+ xmlParseSDDecl (xmlParserCtxtPtr ctxt);
+XMLPUBFUN void XMLCALL
+ xmlParseXMLDecl (xmlParserCtxtPtr ctxt);
+XMLPUBFUN void XMLCALL
+ xmlParseTextDecl (xmlParserCtxtPtr ctxt);
+XMLPUBFUN void XMLCALL
+ xmlParseMisc (xmlParserCtxtPtr ctxt);
+XMLPUBFUN void XMLCALL
+ xmlParseExternalSubset (xmlParserCtxtPtr ctxt,
+ const xmlChar *ExternalID,
+ const xmlChar *SystemID);
+/**
+ * XML_SUBSTITUTE_NONE:
+ *
+ * If no entities need to be substituted.
+ */
+#define XML_SUBSTITUTE_NONE 0
+/**
+ * XML_SUBSTITUTE_REF:
+ *
+ * Whether general entities need to be substituted.
+ */
+#define XML_SUBSTITUTE_REF 1
+/**
+ * XML_SUBSTITUTE_PEREF:
+ *
+ * Whether parameter entities need to be substituted.
+ */
+#define XML_SUBSTITUTE_PEREF 2
+/**
+ * XML_SUBSTITUTE_BOTH:
+ *
+ * Both general and parameter entities need to be substituted.
+ */
+#define XML_SUBSTITUTE_BOTH 3
+
+XMLPUBFUN xmlChar * XMLCALL
+ xmlStringDecodeEntities (xmlParserCtxtPtr ctxt,
+ const xmlChar *str,
+ int what,
+ xmlChar end,
+ xmlChar end2,
+ xmlChar end3);
+XMLPUBFUN xmlChar * XMLCALL
+ xmlStringLenDecodeEntities (xmlParserCtxtPtr ctxt,
+ const xmlChar *str,
+ int len,
+ int what,
+ xmlChar end,
+ xmlChar end2,
+ xmlChar end3);
+
+/*
+ * Generated by MACROS on top of parser.c c.f. PUSH_AND_POP.
+ */
+XMLPUBFUN int XMLCALL nodePush (xmlParserCtxtPtr ctxt,
+ xmlNodePtr value);
+XMLPUBFUN xmlNodePtr XMLCALL nodePop (xmlParserCtxtPtr ctxt);
+XMLPUBFUN int XMLCALL inputPush (xmlParserCtxtPtr ctxt,
+ xmlParserInputPtr value);
+XMLPUBFUN xmlParserInputPtr XMLCALL inputPop (xmlParserCtxtPtr ctxt);
+XMLPUBFUN const xmlChar * XMLCALL namePop (xmlParserCtxtPtr ctxt);
+XMLPUBFUN int XMLCALL namePush (xmlParserCtxtPtr ctxt,
+ const xmlChar *value);
+
+/*
+ * other commodities shared between parser.c and parserInternals.
+ */
+XMLPUBFUN int XMLCALL xmlSkipBlankChars (xmlParserCtxtPtr ctxt);
+XMLPUBFUN int XMLCALL xmlStringCurrentChar (xmlParserCtxtPtr ctxt,
+ const xmlChar *cur,
+ int *len);
+XMLPUBFUN void XMLCALL xmlParserHandlePEReference(xmlParserCtxtPtr ctxt);
+XMLPUBFUN int XMLCALL xmlCheckLanguageID (const xmlChar *lang);
+
+/*
+ * Really core function shared with HTML parser.
+ */
+XMLPUBFUN int XMLCALL xmlCurrentChar (xmlParserCtxtPtr ctxt,
+ int *len);
+XMLPUBFUN int XMLCALL xmlCopyCharMultiByte (xmlChar *out,
+ int val);
+XMLPUBFUN int XMLCALL xmlCopyChar (int len,
+ xmlChar *out,
+ int val);
+XMLPUBFUN void XMLCALL xmlNextChar (xmlParserCtxtPtr ctxt);
+XMLPUBFUN void XMLCALL xmlParserInputShrink (xmlParserInputPtr in);
+
+#ifdef LIBXML_HTML_ENABLED
+/*
+ * Actually comes from the HTML parser but launched from the init stuff.
+ */
+XMLPUBFUN void XMLCALL htmlInitAutoClose (void);
+XMLPUBFUN htmlParserCtxtPtr XMLCALL htmlCreateFileParserCtxt(const char *filename,
+ const char *encoding);
+#endif
+
+/*
+ * Specific function to keep track of entities references
+ * and used by the XSLT debugger.
+ */
+#ifdef LIBXML_LEGACY_ENABLED
+/**
+ * xmlEntityReferenceFunc:
+ * @ent: the entity
+ * @firstNode: the fist node in the chunk
+ * @lastNode: the last nod in the chunk
+ *
+ * Callback function used when one needs to be able to track back the
+ * provenance of a chunk of nodes inherited from an entity replacement.
+ */
+typedef void (*xmlEntityReferenceFunc) (xmlEntityPtr ent,
+ xmlNodePtr firstNode,
+ xmlNodePtr lastNode);
+
+XMLPUBFUN void XMLCALL xmlSetEntityReferenceFunc (xmlEntityReferenceFunc func);
+
+XMLPUBFUN xmlChar * XMLCALL
+ xmlParseQuotedString (xmlParserCtxtPtr ctxt);
+XMLPUBFUN void XMLCALL
+ xmlParseNamespace (xmlParserCtxtPtr ctxt);
+XMLPUBFUN xmlChar * XMLCALL
+ xmlNamespaceParseNSDef (xmlParserCtxtPtr ctxt);
+XMLPUBFUN xmlChar * XMLCALL
+ xmlScanName (xmlParserCtxtPtr ctxt);
+XMLPUBFUN xmlChar * XMLCALL
+ xmlNamespaceParseNCName (xmlParserCtxtPtr ctxt);
+XMLPUBFUN void XMLCALL xmlParserHandleReference(xmlParserCtxtPtr ctxt);
+XMLPUBFUN xmlChar * XMLCALL
+ xmlNamespaceParseQName (xmlParserCtxtPtr ctxt,
+ xmlChar **prefix);
+/**
+ * Entities
+ */
+XMLPUBFUN xmlChar * XMLCALL
+ xmlDecodeEntities (xmlParserCtxtPtr ctxt,
+ int len,
+ int what,
+ xmlChar end,
+ xmlChar end2,
+ xmlChar end3);
+XMLPUBFUN void XMLCALL
+ xmlHandleEntity (xmlParserCtxtPtr ctxt,
+ xmlEntityPtr entity);
+
+#endif /* LIBXML_LEGACY_ENABLED */
+
+#ifdef IN_LIBXML
+/*
+ * internal only
+ */
+XMLPUBFUN void XMLCALL
+ xmlErrMemory (xmlParserCtxtPtr ctxt,
+ const char *extra);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __XML_PARSER_INTERNALS_H__ */
diff --git a/gettext-tools/gnulib-lib/libxml/pattern.c b/gettext-tools/gnulib-lib/libxml/pattern.c
new file mode 100644
index 0000000..cf41606
--- /dev/null
+++ b/gettext-tools/gnulib-lib/libxml/pattern.c
@@ -0,0 +1,2607 @@
+/*
+ * pattern.c: Implemetation of selectors for nodes
+ *
+ * Reference:
+ * http://www.w3.org/TR/2001/REC-xmlschema-1-20010502/
+ * to some extent
+ * http://www.w3.org/TR/1999/REC-xml-19991116
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+
+/*
+ * TODO:
+ * - compilation flags to check for specific syntaxes
+ * using flags of xmlPatterncompile()
+ * - making clear how pattern starting with / or . need to be handled,
+ * currently push(NULL, NULL) means a reset of the streaming context
+ * and indicating we are on / (the document node), probably need
+ * something similar for .
+ * - get rid of the "compile" starting with lowercase
+ * - DONE (2006-05-16): get rid of the Strdup/Strndup in case of dictionary
+ */
+
+#define IN_LIBXML
+#include "libxml.h"
+
+#include <string.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/tree.h>
+#include <libxml/hash.h>
+#include <libxml/dict.h>
+#include <libxml/xmlerror.h>
+#include <libxml/parserInternals.h>
+#include <libxml/pattern.h>
+
+#ifdef LIBXML_PATTERN_ENABLED
+
+/* #define DEBUG_STREAMING */
+
+#define ERROR(a, b, c, d)
+#define ERROR5(a, b, c, d, e)
+
+#define XML_STREAM_STEP_DESC 1
+#define XML_STREAM_STEP_FINAL 2
+#define XML_STREAM_STEP_ROOT 4
+#define XML_STREAM_STEP_ATTR 8
+#define XML_STREAM_STEP_NODE 16
+#define XML_STREAM_STEP_IN_SET 32
+
+/*
+* NOTE: Those private flags (XML_STREAM_xxx) are used
+* in _xmlStreamCtxt->flag. They extend the public
+* xmlPatternFlags, so be carefull not to interfere with the
+* reserved values for xmlPatternFlags.
+*/
+#define XML_STREAM_FINAL_IS_ANY_NODE 1<<14
+#define XML_STREAM_FROM_ROOT 1<<15
+#define XML_STREAM_DESC 1<<16
+
+/*
+* XML_STREAM_ANY_NODE is used for comparison against
+* xmlElementType enums, to indicate a node of any type.
+*/
+#define XML_STREAM_ANY_NODE 100
+
+#define XML_PATTERN_NOTPATTERN (XML_PATTERN_XPATH | \
+ XML_PATTERN_XSSEL | \
+ XML_PATTERN_XSFIELD)
+
+#define XML_STREAM_XS_IDC(c) ((c)->flags & \
+ (XML_PATTERN_XSSEL | XML_PATTERN_XSFIELD))
+
+#define XML_STREAM_XS_IDC_SEL(c) ((c)->flags & XML_PATTERN_XSSEL)
+
+#define XML_STREAM_XS_IDC_FIELD(c) ((c)->flags & XML_PATTERN_XSFIELD)
+
+#define XML_PAT_COPY_NSNAME(c, r, nsname) \
+ if ((c)->comp->dict) \
+ r = (xmlChar *) xmlDictLookup((c)->comp->dict, BAD_CAST nsname, -1); \
+ else r = xmlStrdup(BAD_CAST nsname);
+
+#define XML_PAT_FREE_STRING(c, r) if ((c)->comp->dict == NULL) xmlFree(r);
+
+typedef struct _xmlStreamStep xmlStreamStep;
+typedef xmlStreamStep *xmlStreamStepPtr;
+struct _xmlStreamStep {
+ int flags; /* properties of that step */
+ const xmlChar *name; /* first string value if NULL accept all */
+ const xmlChar *ns; /* second string value */
+ int nodeType; /* type of node */
+};
+
+typedef struct _xmlStreamComp xmlStreamComp;
+typedef xmlStreamComp *xmlStreamCompPtr;
+struct _xmlStreamComp {
+ xmlDict *dict; /* the dictionary if any */
+ int nbStep; /* number of steps in the automata */
+ int maxStep; /* allocated number of steps */
+ xmlStreamStepPtr steps; /* the array of steps */
+ int flags;
+};
+
+struct _xmlStreamCtxt {
+ struct _xmlStreamCtxt *next;/* link to next sub pattern if | */
+ xmlStreamCompPtr comp; /* the compiled stream */
+ int nbState; /* number of states in the automata */
+ int maxState; /* allocated number of states */
+ int level; /* how deep are we ? */
+ int *states; /* the array of step indexes */
+ int flags; /* validation options */
+ int blockLevel;
+};
+
+static void xmlFreeStreamComp(xmlStreamCompPtr comp);
+
+/*
+ * Types are private:
+ */
+
+typedef enum {
+ XML_OP_END=0,
+ XML_OP_ROOT,
+ XML_OP_ELEM,
+ XML_OP_CHILD,
+ XML_OP_ATTR,
+ XML_OP_PARENT,
+ XML_OP_ANCESTOR,
+ XML_OP_NS,
+ XML_OP_ALL
+} xmlPatOp;
+
+
+typedef struct _xmlStepState xmlStepState;
+typedef xmlStepState *xmlStepStatePtr;
+struct _xmlStepState {
+ int step;
+ xmlNodePtr node;
+};
+
+typedef struct _xmlStepStates xmlStepStates;
+typedef xmlStepStates *xmlStepStatesPtr;
+struct _xmlStepStates {
+ int nbstates;
+ int maxstates;
+ xmlStepStatePtr states;
+};
+
+typedef struct _xmlStepOp xmlStepOp;
+typedef xmlStepOp *xmlStepOpPtr;
+struct _xmlStepOp {
+ xmlPatOp op;
+ const xmlChar *value;
+ const xmlChar *value2; /* The namespace name */
+};
+
+#define PAT_FROM_ROOT (1<<8)
+#define PAT_FROM_CUR (1<<9)
+
+struct _xmlPattern {
+ void *data; /* the associated template */
+ xmlDictPtr dict; /* the optional dictionary */
+ struct _xmlPattern *next; /* next pattern if | is used */
+ const xmlChar *pattern; /* the pattern */
+ int flags; /* flags */
+ int nbStep;
+ int maxStep;
+ xmlStepOpPtr steps; /* ops for computation */
+ xmlStreamCompPtr stream; /* the streaming data if any */
+};
+
+typedef struct _xmlPatParserContext xmlPatParserContext;
+typedef xmlPatParserContext *xmlPatParserContextPtr;
+struct _xmlPatParserContext {
+ const xmlChar *cur; /* the current char being parsed */
+ const xmlChar *base; /* the full expression */
+ int error; /* error code */
+ xmlDictPtr dict; /* the dictionary if any */
+ xmlPatternPtr comp; /* the result */
+ xmlNodePtr elem; /* the current node if any */
+ const xmlChar **namespaces; /* the namespaces definitions */
+ int nb_namespaces; /* the number of namespaces */
+};
+
+/************************************************************************
+ * *
+ * Type functions *
+ * *
+ ************************************************************************/
+
+/**
+ * xmlNewPattern:
+ *
+ * Create a new XSLT Pattern
+ *
+ * Returns the newly allocated xmlPatternPtr or NULL in case of error
+ */
+static xmlPatternPtr
+xmlNewPattern(void) {
+ xmlPatternPtr cur;
+
+ cur = (xmlPatternPtr) xmlMalloc(sizeof(xmlPattern));
+ if (cur == NULL) {
+ ERROR(NULL, NULL, NULL,
+ "xmlNewPattern : malloc failed\n");
+ return(NULL);
+ }
+ memset(cur, 0, sizeof(xmlPattern));
+ cur->maxStep = 10;
+ cur->steps = (xmlStepOpPtr) xmlMalloc(cur->maxStep * sizeof(xmlStepOp));
+ if (cur->steps == NULL) {
+ xmlFree(cur);
+ ERROR(NULL, NULL, NULL,
+ "xmlNewPattern : malloc failed\n");
+ return(NULL);
+ }
+ return(cur);
+}
+
+/**
+ * xmlFreePattern:
+ * @comp: an XSLT comp
+ *
+ * Free up the memory allocated by @comp
+ */
+void
+xmlFreePattern(xmlPatternPtr comp) {
+ xmlStepOpPtr op;
+ int i;
+
+ if (comp == NULL)
+ return;
+ if (comp->next != NULL)
+ xmlFreePattern(comp->next);
+ if (comp->stream != NULL)
+ xmlFreeStreamComp(comp->stream);
+ if (comp->pattern != NULL)
+ xmlFree((xmlChar *)comp->pattern);
+ if (comp->steps != NULL) {
+ if (comp->dict == NULL) {
+ for (i = 0;i < comp->nbStep;i++) {
+ op = &comp->steps[i];
+ if (op->value != NULL)
+ xmlFree((xmlChar *) op->value);
+ if (op->value2 != NULL)
+ xmlFree((xmlChar *) op->value2);
+ }
+ }
+ xmlFree(comp->steps);
+ }
+ if (comp->dict != NULL)
+ xmlDictFree(comp->dict);
+
+ memset(comp, -1, sizeof(xmlPattern));
+ xmlFree(comp);
+}
+
+/**
+ * xmlFreePatternList:
+ * @comp: an XSLT comp list
+ *
+ * Free up the memory allocated by all the elements of @comp
+ */
+void
+xmlFreePatternList(xmlPatternPtr comp) {
+ xmlPatternPtr cur;
+
+ while (comp != NULL) {
+ cur = comp;
+ comp = comp->next;
+ cur->next = NULL;
+ xmlFreePattern(cur);
+ }
+}
+
+/**
+ * xmlNewPatParserContext:
+ * @pattern: the pattern context
+ * @dict: the inherited dictionary or NULL
+ * @namespaces: the prefix definitions, array of [URI, prefix] terminated
+ * with [NULL, NULL] or NULL if no namespace is used
+ *
+ * Create a new XML pattern parser context
+ *
+ * Returns the newly allocated xmlPatParserContextPtr or NULL in case of error
+ */
+static xmlPatParserContextPtr
+xmlNewPatParserContext(const xmlChar *pattern, xmlDictPtr dict,
+ const xmlChar **namespaces) {
+ xmlPatParserContextPtr cur;
+
+ if (pattern == NULL)
+ return(NULL);
+
+ cur = (xmlPatParserContextPtr) xmlMalloc(sizeof(xmlPatParserContext));
+ if (cur == NULL) {
+ ERROR(NULL, NULL, NULL,
+ "xmlNewPatParserContext : malloc failed\n");
+ return(NULL);
+ }
+ memset(cur, 0, sizeof(xmlPatParserContext));
+ cur->dict = dict;
+ cur->cur = pattern;
+ cur->base = pattern;
+ if (namespaces != NULL) {
+ int i;
+ for (i = 0;namespaces[2 * i] != NULL;i++);
+ cur->nb_namespaces = i;
+ } else {
+ cur->nb_namespaces = 0;
+ }
+ cur->namespaces = namespaces;
+ return(cur);
+}
+
+/**
+ * xmlFreePatParserContext:
+ * @ctxt: an XSLT parser context
+ *
+ * Free up the memory allocated by @ctxt
+ */
+static void
+xmlFreePatParserContext(xmlPatParserContextPtr ctxt) {
+ if (ctxt == NULL)
+ return;
+ memset(ctxt, -1, sizeof(xmlPatParserContext));
+ xmlFree(ctxt);
+}
+
+/**
+ * xmlPatternAdd:
+ * @comp: the compiled match expression
+ * @op: an op
+ * @value: the first value
+ * @value2: the second value
+ *
+ * Add a step to an XSLT Compiled Match
+ *
+ * Returns -1 in case of failure, 0 otherwise.
+ */
+static int
+xmlPatternAdd(xmlPatParserContextPtr ctxt ATTRIBUTE_UNUSED,
+ xmlPatternPtr comp,
+ xmlPatOp op, xmlChar * value, xmlChar * value2)
+{
+ if (comp->nbStep >= comp->maxStep) {
+ xmlStepOpPtr temp;
+ temp = (xmlStepOpPtr) xmlRealloc(comp->steps, comp->maxStep * 2 *
+ sizeof(xmlStepOp));
+ if (temp == NULL) {
+ ERROR(ctxt, NULL, NULL,
+ "xmlPatternAdd: realloc failed\n");
+ return (-1);
+ }
+ comp->steps = temp;
+ comp->maxStep *= 2;
+ }
+ comp->steps[comp->nbStep].op = op;
+ comp->steps[comp->nbStep].value = value;
+ comp->steps[comp->nbStep].value2 = value2;
+ comp->nbStep++;
+ return (0);
+}
+
+#if 0
+/**
+ * xsltSwapTopPattern:
+ * @comp: the compiled match expression
+ *
+ * reverse the two top steps.
+ */
+static void
+xsltSwapTopPattern(xmlPatternPtr comp) {
+ int i;
+ int j = comp->nbStep - 1;
+
+ if (j > 0) {
+ register const xmlChar *tmp;
+ register xmlPatOp op;
+ i = j - 1;
+ tmp = comp->steps[i].value;
+ comp->steps[i].value = comp->steps[j].value;
+ comp->steps[j].value = tmp;
+ tmp = comp->steps[i].value2;
+ comp->steps[i].value2 = comp->steps[j].value2;
+ comp->steps[j].value2 = tmp;
+ op = comp->steps[i].op;
+ comp->steps[i].op = comp->steps[j].op;
+ comp->steps[j].op = op;
+ }
+}
+#endif
+
+/**
+ * xmlReversePattern:
+ * @comp: the compiled match expression
+ *
+ * reverse all the stack of expressions
+ *
+ * returns 0 in case of success and -1 in case of error.
+ */
+static int
+xmlReversePattern(xmlPatternPtr comp) {
+ int i, j;
+
+ /*
+ * remove the leading // for //a or .//a
+ */
+ if ((comp->nbStep > 0) && (comp->steps[0].op == XML_OP_ANCESTOR)) {
+ for (i = 0, j = 1;j < comp->nbStep;i++,j++) {
+ comp->steps[i].value = comp->steps[j].value;
+ comp->steps[i].value2 = comp->steps[j].value2;
+ comp->steps[i].op = comp->steps[j].op;
+ }
+ comp->nbStep--;
+ }
+ if (comp->nbStep >= comp->maxStep) {
+ xmlStepOpPtr temp;
+ temp = (xmlStepOpPtr) xmlRealloc(comp->steps, comp->maxStep * 2 *
+ sizeof(xmlStepOp));
+ if (temp == NULL) {
+ ERROR(ctxt, NULL, NULL,
+ "xmlReversePattern: realloc failed\n");
+ return (-1);
+ }
+ comp->steps = temp;
+ comp->maxStep *= 2;
+ }
+ i = 0;
+ j = comp->nbStep - 1;
+ while (j > i) {
+ register const xmlChar *tmp;
+ register xmlPatOp op;
+ tmp = comp->steps[i].value;
+ comp->steps[i].value = comp->steps[j].value;
+ comp->steps[j].value = tmp;
+ tmp = comp->steps[i].value2;
+ comp->steps[i].value2 = comp->steps[j].value2;
+ comp->steps[j].value2 = tmp;
+ op = comp->steps[i].op;
+ comp->steps[i].op = comp->steps[j].op;
+ comp->steps[j].op = op;
+ j--;
+ i++;
+ }
+ comp->steps[comp->nbStep].value = NULL;
+ comp->steps[comp->nbStep].value2 = NULL;
+ comp->steps[comp->nbStep++].op = XML_OP_END;
+ return(0);
+}
+
+/************************************************************************
+ * *
+ * The interpreter for the precompiled patterns *
+ * *
+ ************************************************************************/
+
+static int
+xmlPatPushState(xmlStepStates *states, int step, xmlNodePtr node) {
+ if ((states->states == NULL) || (states->maxstates <= 0)) {
+ states->maxstates = 4;
+ states->nbstates = 0;
+ states->states = xmlMalloc(4 * sizeof(xmlStepState));
+ }
+ else if (states->maxstates <= states->nbstates) {
+ xmlStepState *tmp;
+
+ tmp = (xmlStepStatePtr) xmlRealloc(states->states,
+ 2 * states->maxstates * sizeof(xmlStepState));
+ if (tmp == NULL)
+ return(-1);
+ states->states = tmp;
+ states->maxstates *= 2;
+ }
+ states->states[states->nbstates].step = step;
+ states->states[states->nbstates++].node = node;
+#if 0
+ fprintf(stderr, "Push: %d, %s\n", step, node->name);
+#endif
+ return(0);
+}
+
+/**
+ * xmlPatMatch:
+ * @comp: the precompiled pattern
+ * @node: a node
+ *
+ * Test whether the node matches the pattern
+ *
+ * Returns 1 if it matches, 0 if it doesn't and -1 in case of failure
+ */
+static int
+xmlPatMatch(xmlPatternPtr comp, xmlNodePtr node) {
+ int i;
+ xmlStepOpPtr step;
+ xmlStepStates states = {0, 0, NULL}; /* // may require backtrack */
+
+ if ((comp == NULL) || (node == NULL)) return(-1);
+ i = 0;
+restart:
+ for (;i < comp->nbStep;i++) {
+ step = &comp->steps[i];
+ switch (step->op) {
+ case XML_OP_END:
+ goto found;
+ case XML_OP_ROOT:
+ if (node->type == XML_NAMESPACE_DECL)
+ goto rollback;
+ node = node->parent;
+ if ((node->type == XML_DOCUMENT_NODE) ||
+#ifdef LIBXML_DOCB_ENABLED
+ (node->type == XML_DOCB_DOCUMENT_NODE) ||
+#endif
+ (node->type == XML_HTML_DOCUMENT_NODE))
+ continue;
+ goto rollback;
+ case XML_OP_ELEM:
+ if (node->type != XML_ELEMENT_NODE)
+ goto rollback;
+ if (step->value == NULL)
+ continue;
+ if (step->value[0] != node->name[0])
+ goto rollback;
+ if (!xmlStrEqual(step->value, node->name))
+ goto rollback;
+
+ /* Namespace test */
+ if (node->ns == NULL) {
+ if (step->value2 != NULL)
+ goto rollback;
+ } else if (node->ns->href != NULL) {
+ if (step->value2 == NULL)
+ goto rollback;
+ if (!xmlStrEqual(step->value2, node->ns->href))
+ goto rollback;
+ }
+ continue;
+ case XML_OP_CHILD: {
+ xmlNodePtr lst;
+
+ if ((node->type != XML_ELEMENT_NODE) &&
+ (node->type != XML_DOCUMENT_NODE) &&
+#ifdef LIBXML_DOCB_ENABLED
+ (node->type != XML_DOCB_DOCUMENT_NODE) &&
+#endif
+ (node->type != XML_HTML_DOCUMENT_NODE))
+ goto rollback;
+
+ lst = node->children;
+
+ if (step->value != NULL) {
+ while (lst != NULL) {
+ if ((lst->type == XML_ELEMENT_NODE) &&
+ (step->value[0] == lst->name[0]) &&
+ (xmlStrEqual(step->value, lst->name)))
+ break;
+ lst = lst->next;
+ }
+ if (lst != NULL)
+ continue;
+ }
+ goto rollback;
+ }
+ case XML_OP_ATTR:
+ if (node->type != XML_ATTRIBUTE_NODE)
+ goto rollback;
+ if (step->value != NULL) {
+ if (step->value[0] != node->name[0])
+ goto rollback;
+ if (!xmlStrEqual(step->value, node->name))
+ goto rollback;
+ }
+ /* Namespace test */
+ if (node->ns == NULL) {
+ if (step->value2 != NULL)
+ goto rollback;
+ } else if (step->value2 != NULL) {
+ if (!xmlStrEqual(step->value2, node->ns->href))
+ goto rollback;
+ }
+ continue;
+ case XML_OP_PARENT:
+ if ((node->type == XML_DOCUMENT_NODE) ||
+ (node->type == XML_HTML_DOCUMENT_NODE) ||
+#ifdef LIBXML_DOCB_ENABLED
+ (node->type == XML_DOCB_DOCUMENT_NODE) ||
+#endif
+ (node->type == XML_NAMESPACE_DECL))
+ goto rollback;
+ node = node->parent;
+ if (node == NULL)
+ goto rollback;
+ if (step->value == NULL)
+ continue;
+ if (step->value[0] != node->name[0])
+ goto rollback;
+ if (!xmlStrEqual(step->value, node->name))
+ goto rollback;
+ /* Namespace test */
+ if (node->ns == NULL) {
+ if (step->value2 != NULL)
+ goto rollback;
+ } else if (node->ns->href != NULL) {
+ if (step->value2 == NULL)
+ goto rollback;
+ if (!xmlStrEqual(step->value2, node->ns->href))
+ goto rollback;
+ }
+ continue;
+ case XML_OP_ANCESTOR:
+ /* TODO: implement coalescing of ANCESTOR/NODE ops */
+ if (step->value == NULL) {
+ i++;
+ step = &comp->steps[i];
+ if (step->op == XML_OP_ROOT)
+ goto found;
+ if (step->op != XML_OP_ELEM)
+ goto rollback;
+ if (step->value == NULL)
+ return(-1);
+ }
+ if (node == NULL)
+ goto rollback;
+ if ((node->type == XML_DOCUMENT_NODE) ||
+ (node->type == XML_HTML_DOCUMENT_NODE) ||
+#ifdef LIBXML_DOCB_ENABLED
+ (node->type == XML_DOCB_DOCUMENT_NODE) ||
+#endif
+ (node->type == XML_NAMESPACE_DECL))
+ goto rollback;
+ node = node->parent;
+ while (node != NULL) {
+ if ((node->type == XML_ELEMENT_NODE) &&
+ (step->value[0] == node->name[0]) &&
+ (xmlStrEqual(step->value, node->name))) {
+ /* Namespace test */
+ if (node->ns == NULL) {
+ if (step->value2 == NULL)
+ break;
+ } else if (node->ns->href != NULL) {
+ if ((step->value2 != NULL) &&
+ (xmlStrEqual(step->value2, node->ns->href)))
+ break;
+ }
+ }
+ node = node->parent;
+ }
+ if (node == NULL)
+ goto rollback;
+ /*
+ * prepare a potential rollback from here
+ * for ancestors of that node.
+ */
+ if (step->op == XML_OP_ANCESTOR)
+ xmlPatPushState(&states, i, node);
+ else
+ xmlPatPushState(&states, i - 1, node);
+ continue;
+ case XML_OP_NS:
+ if (node->type != XML_ELEMENT_NODE)
+ goto rollback;
+ if (node->ns == NULL) {
+ if (step->value != NULL)
+ goto rollback;
+ } else if (node->ns->href != NULL) {
+ if (step->value == NULL)
+ goto rollback;
+ if (!xmlStrEqual(step->value, node->ns->href))
+ goto rollback;
+ }
+ break;
+ case XML_OP_ALL:
+ if (node->type != XML_ELEMENT_NODE)
+ goto rollback;
+ break;
+ }
+ }
+found:
+ if (states.states != NULL) {
+ /* Free the rollback states */
+ xmlFree(states.states);
+ }
+ return(1);
+rollback:
+ /* got an error try to rollback */
+ if (states.states == NULL)
+ return(0);
+ if (states.nbstates <= 0) {
+ xmlFree(states.states);
+ return(0);
+ }
+ states.nbstates--;
+ i = states.states[states.nbstates].step;
+ node = states.states[states.nbstates].node;
+#if 0
+ fprintf(stderr, "Pop: %d, %s\n", i, node->name);
+#endif
+ goto restart;
+}
+
+/************************************************************************
+ * *
+ * Dedicated parser for templates *
+ * *
+ ************************************************************************/
+
+#define TODO \
+ xmlGenericError(xmlGenericErrorContext, \
+ "Unimplemented block at %s:%d\n", \
+ __FILE__, __LINE__);
+#define CUR (*ctxt->cur)
+#define SKIP(val) ctxt->cur += (val)
+#define NXT(val) ctxt->cur[(val)]
+#define PEEKPREV(val) ctxt->cur[-(val)]
+#define CUR_PTR ctxt->cur
+
+#define SKIP_BLANKS \
+ while (IS_BLANK_CH(CUR)) NEXT
+
+#define CURRENT (*ctxt->cur)
+#define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur)
+
+
+#define PUSH(op, val, val2) \
+ if (xmlPatternAdd(ctxt, ctxt->comp, (op), (val), (val2))) goto error;
+
+#define XSLT_ERROR(X) \
+ { xsltError(ctxt, __FILE__, __LINE__, X); \
+ ctxt->error = (X); return; }
+
+#define XSLT_ERROR0(X) \
+ { xsltError(ctxt, __FILE__, __LINE__, X); \
+ ctxt->error = (X); return(0); }
+
+#if 0
+/**
+ * xmlPatScanLiteral:
+ * @ctxt: the XPath Parser context
+ *
+ * Parse an XPath Litteral:
+ *
+ * [29] Literal ::= '"' [^"]* '"'
+ * | "'" [^']* "'"
+ *
+ * Returns the Literal parsed or NULL
+ */
+
+static xmlChar *
+xmlPatScanLiteral(xmlPatParserContextPtr ctxt) {
+ const xmlChar *q, *cur;
+ xmlChar *ret = NULL;
+ int val, len;
+
+ SKIP_BLANKS;
+ if (CUR == '"') {
+ NEXT;
+ cur = q = CUR_PTR;
+ val = xmlStringCurrentChar(NULL, cur, &len);
+ while ((IS_CHAR(val)) && (val != '"')) {
+ cur += len;
+ val = xmlStringCurrentChar(NULL, cur, &len);
+ }
+ if (!IS_CHAR(val)) {
+ ctxt->error = 1;
+ return(NULL);
+ } else {
+ if (ctxt->dict)
+ ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q);
+ else
+ ret = xmlStrndup(q, cur - q);
+ }
+ cur += len;
+ CUR_PTR = cur;
+ } else if (CUR == '\'') {
+ NEXT;
+ cur = q = CUR_PTR;
+ val = xmlStringCurrentChar(NULL, cur, &len);
+ while ((IS_CHAR(val)) && (val != '\'')) {
+ cur += len;
+ val = xmlStringCurrentChar(NULL, cur, &len);
+ }
+ if (!IS_CHAR(val)) {
+ ctxt->error = 1;
+ return(NULL);
+ } else {
+ if (ctxt->dict)
+ ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q);
+ else
+ ret = xmlStrndup(q, cur - q);
+ }
+ cur += len;
+ CUR_PTR = cur;
+ } else {
+ /* XP_ERROR(XPATH_START_LITERAL_ERROR); */
+ ctxt->error = 1;
+ return(NULL);
+ }
+ return(ret);
+}
+#endif
+
+/**
+ * xmlPatScanName:
+ * @ctxt: the XPath Parser context
+ *
+ * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' |
+ * CombiningChar | Extender
+ *
+ * [5] Name ::= (Letter | '_' | ':') (NameChar)*
+ *
+ * [6] Names ::= Name (S Name)*
+ *
+ * Returns the Name parsed or NULL
+ */
+
+static xmlChar *
+xmlPatScanName(xmlPatParserContextPtr ctxt) {
+ const xmlChar *q, *cur;
+ xmlChar *ret = NULL;
+ int val, len;
+
+ SKIP_BLANKS;
+
+ cur = q = CUR_PTR;
+ val = xmlStringCurrentChar(NULL, cur, &len);
+ if (!IS_LETTER(val) && (val != '_') && (val != ':'))
+ return(NULL);
+
+ while ((IS_LETTER(val)) || (IS_DIGIT(val)) ||
+ (val == '.') || (val == '-') ||
+ (val == '_') ||
+ (IS_COMBINING(val)) ||
+ (IS_EXTENDER(val))) {
+ cur += len;
+ val = xmlStringCurrentChar(NULL, cur, &len);
+ }
+ if (ctxt->dict)
+ ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q);
+ else
+ ret = xmlStrndup(q, cur - q);
+ CUR_PTR = cur;
+ return(ret);
+}
+
+/**
+ * xmlPatScanNCName:
+ * @ctxt: the XPath Parser context
+ *
+ * Parses a non qualified name
+ *
+ * Returns the Name parsed or NULL
+ */
+
+static xmlChar *
+xmlPatScanNCName(xmlPatParserContextPtr ctxt) {
+ const xmlChar *q, *cur;
+ xmlChar *ret = NULL;
+ int val, len;
+
+ SKIP_BLANKS;
+
+ cur = q = CUR_PTR;
+ val = xmlStringCurrentChar(NULL, cur, &len);
+ if (!IS_LETTER(val) && (val != '_'))
+ return(NULL);
+
+ while ((IS_LETTER(val)) || (IS_DIGIT(val)) ||
+ (val == '.') || (val == '-') ||
+ (val == '_') ||
+ (IS_COMBINING(val)) ||
+ (IS_EXTENDER(val))) {
+ cur += len;
+ val = xmlStringCurrentChar(NULL, cur, &len);
+ }
+ if (ctxt->dict)
+ ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q);
+ else
+ ret = xmlStrndup(q, cur - q);
+ CUR_PTR = cur;
+ return(ret);
+}
+
+#if 0
+/**
+ * xmlPatScanQName:
+ * @ctxt: the XPath Parser context
+ * @prefix: the place to store the prefix
+ *
+ * Parse a qualified name
+ *
+ * Returns the Name parsed or NULL
+ */
+
+static xmlChar *
+xmlPatScanQName(xmlPatParserContextPtr ctxt, xmlChar **prefix) {
+ xmlChar *ret = NULL;
+
+ *prefix = NULL;
+ ret = xmlPatScanNCName(ctxt);
+ if (CUR == ':') {
+ *prefix = ret;
+ NEXT;
+ ret = xmlPatScanNCName(ctxt);
+ }
+ return(ret);
+}
+#endif
+
+/**
+ * xmlCompileAttributeTest:
+ * @ctxt: the compilation context
+ *
+ * Compile an attribute test.
+ */
+static void
+xmlCompileAttributeTest(xmlPatParserContextPtr ctxt) {
+ xmlChar *token = NULL;
+ xmlChar *name = NULL;
+ xmlChar *URL = NULL;
+
+ SKIP_BLANKS;
+ name = xmlPatScanNCName(ctxt);
+ if (name == NULL) {
+ if (CUR == '*') {
+ PUSH(XML_OP_ATTR, NULL, NULL);
+ NEXT;
+ } else {
+ ERROR(NULL, NULL, NULL,
+ "xmlCompileAttributeTest : Name expected\n");
+ ctxt->error = 1;
+ }
+ return;
+ }
+ if (CUR == ':') {
+ int i;
+ xmlChar *prefix = name;
+
+ NEXT;
+
+ if (IS_BLANK_CH(CUR)) {
+ ERROR5(NULL, NULL, NULL, "Invalid QName.\n", NULL);
+ XML_PAT_FREE_STRING(ctxt, prefix);
+ ctxt->error = 1;
+ goto error;
+ }
+ /*
+ * This is a namespace match
+ */
+ token = xmlPatScanName(ctxt);
+ if ((prefix[0] == 'x') &&
+ (prefix[1] == 'm') &&
+ (prefix[2] == 'l') &&
+ (prefix[3] == 0))
+ {
+ XML_PAT_COPY_NSNAME(ctxt, URL, XML_XML_NAMESPACE);
+ } else {
+ for (i = 0;i < ctxt->nb_namespaces;i++) {
+ if (xmlStrEqual(ctxt->namespaces[2 * i + 1], prefix)) {
+ XML_PAT_COPY_NSNAME(ctxt, URL, ctxt->namespaces[2 * i])
+ break;
+ }
+ }
+ if (i >= ctxt->nb_namespaces) {
+ ERROR5(NULL, NULL, NULL,
+ "xmlCompileAttributeTest : no namespace bound to prefix %s\n",
+ prefix);
+ ctxt->error = 1;
+ goto error;
+ }
+ }
+ XML_PAT_FREE_STRING(ctxt, prefix);
+ if (token == NULL) {
+ if (CUR == '*') {
+ NEXT;
+ PUSH(XML_OP_ATTR, NULL, URL);
+ } else {
+ ERROR(NULL, NULL, NULL,
+ "xmlCompileAttributeTest : Name expected\n");
+ ctxt->error = 1;
+ goto error;
+ }
+ } else {
+ PUSH(XML_OP_ATTR, token, URL);
+ }
+ } else {
+ PUSH(XML_OP_ATTR, name, NULL);
+ }
+ return;
+error:
+ if (URL != NULL)
+ XML_PAT_FREE_STRING(ctxt, URL)
+ if (token != NULL)
+ XML_PAT_FREE_STRING(ctxt, token);
+}
+
+/**
+ * xmlCompileStepPattern:
+ * @ctxt: the compilation context
+ *
+ * Compile the Step Pattern and generates a precompiled
+ * form suitable for fast matching.
+ *
+ * [3] Step ::= '.' | NameTest
+ * [4] NameTest ::= QName | '*' | NCName ':' '*'
+ */
+
+static void
+xmlCompileStepPattern(xmlPatParserContextPtr ctxt) {
+ xmlChar *token = NULL;
+ xmlChar *name = NULL;
+ xmlChar *URL = NULL;
+ int hasBlanks = 0;
+
+ SKIP_BLANKS;
+ if (CUR == '.') {
+ /*
+ * Context node.
+ */
+ NEXT;
+ PUSH(XML_OP_ELEM, NULL, NULL);
+ return;
+ }
+ if (CUR == '@') {
+ /*
+ * Attribute test.
+ */
+ if (XML_STREAM_XS_IDC_SEL(ctxt->comp)) {
+ ERROR5(NULL, NULL, NULL,
+ "Unexpected attribute axis in '%s'.\n", ctxt->base);
+ ctxt->error = 1;
+ return;
+ }
+ NEXT;
+ xmlCompileAttributeTest(ctxt);
+ if (ctxt->error != 0)
+ goto error;
+ return;
+ }
+ name = xmlPatScanNCName(ctxt);
+ if (name == NULL) {
+ if (CUR == '*') {
+ NEXT;
+ PUSH(XML_OP_ALL, NULL, NULL);
+ return;
+ } else {
+ ERROR(NULL, NULL, NULL,
+ "xmlCompileStepPattern : Name expected\n");
+ ctxt->error = 1;
+ return;
+ }
+ }
+ if (IS_BLANK_CH(CUR)) {
+ hasBlanks = 1;
+ SKIP_BLANKS;
+ }
+ if (CUR == ':') {
+ NEXT;
+ if (CUR != ':') {
+ xmlChar *prefix = name;
+ int i;
+
+ if (hasBlanks || IS_BLANK_CH(CUR)) {
+ ERROR5(NULL, NULL, NULL, "Invalid QName.\n", NULL);
+ ctxt->error = 1;
+ goto error;
+ }
+ /*
+ * This is a namespace match
+ */
+ token = xmlPatScanName(ctxt);
+ if ((prefix[0] == 'x') &&
+ (prefix[1] == 'm') &&
+ (prefix[2] == 'l') &&
+ (prefix[3] == 0))
+ {
+ XML_PAT_COPY_NSNAME(ctxt, URL, XML_XML_NAMESPACE)
+ } else {
+ for (i = 0;i < ctxt->nb_namespaces;i++) {
+ if (xmlStrEqual(ctxt->namespaces[2 * i + 1], prefix)) {
+ XML_PAT_COPY_NSNAME(ctxt, URL, ctxt->namespaces[2 * i])
+ break;
+ }
+ }
+ if (i >= ctxt->nb_namespaces) {
+ ERROR5(NULL, NULL, NULL,
+ "xmlCompileStepPattern : no namespace bound to prefix %s\n",
+ prefix);
+ ctxt->error = 1;
+ goto error;
+ }
+ }
+ XML_PAT_FREE_STRING(ctxt, prefix);
+ if (token == NULL) {
+ if (CUR == '*') {
+ NEXT;
+ PUSH(XML_OP_NS, URL, NULL);
+ } else {
+ ERROR(NULL, NULL, NULL,
+ "xmlCompileStepPattern : Name expected\n");
+ ctxt->error = 1;
+ goto error;
+ }
+ } else {
+ PUSH(XML_OP_ELEM, token, URL);
+ }
+ } else {
+ NEXT;
+ if (xmlStrEqual(name, (const xmlChar *) "child")) {
+ XML_PAT_FREE_STRING(ctxt, name);
+ name = xmlPatScanName(ctxt);
+ if (name == NULL) {
+ if (CUR == '*') {
+ NEXT;
+ PUSH(XML_OP_ALL, NULL, NULL);
+ return;
+ } else {
+ ERROR(NULL, NULL, NULL,
+ "xmlCompileStepPattern : QName expected\n");
+ ctxt->error = 1;
+ goto error;
+ }
+ }
+ if (CUR == ':') {
+ xmlChar *prefix = name;
+ int i;
+
+ NEXT;
+ if (IS_BLANK_CH(CUR)) {
+ ERROR5(NULL, NULL, NULL, "Invalid QName.\n", NULL);
+ ctxt->error = 1;
+ goto error;
+ }
+ /*
+ * This is a namespace match
+ */
+ token = xmlPatScanName(ctxt);
+ if ((prefix[0] == 'x') &&
+ (prefix[1] == 'm') &&
+ (prefix[2] == 'l') &&
+ (prefix[3] == 0))
+ {
+ XML_PAT_COPY_NSNAME(ctxt, URL, XML_XML_NAMESPACE)
+ } else {
+ for (i = 0;i < ctxt->nb_namespaces;i++) {
+ if (xmlStrEqual(ctxt->namespaces[2 * i + 1], prefix)) {
+ XML_PAT_COPY_NSNAME(ctxt, URL, ctxt->namespaces[2 * i])
+ break;
+ }
+ }
+ if (i >= ctxt->nb_namespaces) {
+ ERROR5(NULL, NULL, NULL,
+ "xmlCompileStepPattern : no namespace bound "
+ "to prefix %s\n", prefix);
+ ctxt->error = 1;
+ goto error;
+ }
+ }
+ XML_PAT_FREE_STRING(ctxt, prefix);
+ if (token == NULL) {
+ if (CUR == '*') {
+ NEXT;
+ PUSH(XML_OP_NS, URL, NULL);
+ } else {
+ ERROR(NULL, NULL, NULL,
+ "xmlCompileStepPattern : Name expected\n");
+ ctxt->error = 1;
+ goto error;
+ }
+ } else {
+ PUSH(XML_OP_CHILD, token, URL);
+ }
+ } else
+ PUSH(XML_OP_CHILD, name, NULL);
+ return;
+ } else if (xmlStrEqual(name, (const xmlChar *) "attribute")) {
+ XML_PAT_FREE_STRING(ctxt, name)
+ name = NULL;
+ if (XML_STREAM_XS_IDC_SEL(ctxt->comp)) {
+ ERROR5(NULL, NULL, NULL,
+ "Unexpected attribute axis in '%s'.\n", ctxt->base);
+ ctxt->error = 1;
+ goto error;
+ }
+ xmlCompileAttributeTest(ctxt);
+ if (ctxt->error != 0)
+ goto error;
+ return;
+ } else {
+ ERROR5(NULL, NULL, NULL,
+ "The 'element' or 'attribute' axis is expected.\n", NULL);
+ ctxt->error = 1;
+ goto error;
+ }
+ }
+ } else if (CUR == '*') {
+ if (name != NULL) {
+ ctxt->error = 1;
+ goto error;
+ }
+ NEXT;
+ PUSH(XML_OP_ALL, token, NULL);
+ } else {
+ PUSH(XML_OP_ELEM, name, NULL);
+ }
+ return;
+error:
+ if (URL != NULL)
+ XML_PAT_FREE_STRING(ctxt, URL)
+ if (token != NULL)
+ XML_PAT_FREE_STRING(ctxt, token)
+ if (name != NULL)
+ XML_PAT_FREE_STRING(ctxt, name)
+}
+
+/**
+ * xmlCompilePathPattern:
+ * @ctxt: the compilation context
+ *
+ * Compile the Path Pattern and generates a precompiled
+ * form suitable for fast matching.
+ *
+ * [5] Path ::= ('.//')? ( Step '/' )* ( Step | '@' NameTest )
+ */
+static void
+xmlCompilePathPattern(xmlPatParserContextPtr ctxt) {
+ SKIP_BLANKS;
+ if (CUR == '/') {
+ ctxt->comp->flags |= PAT_FROM_ROOT;
+ } else if ((CUR == '.') || (ctxt->comp->flags & XML_PATTERN_NOTPATTERN)) {
+ ctxt->comp->flags |= PAT_FROM_CUR;
+ }
+
+ if ((CUR == '/') && (NXT(1) == '/')) {
+ PUSH(XML_OP_ANCESTOR, NULL, NULL);
+ NEXT;
+ NEXT;
+ } else if ((CUR == '.') && (NXT(1) == '/') && (NXT(2) == '/')) {
+ PUSH(XML_OP_ANCESTOR, NULL, NULL);
+ NEXT;
+ NEXT;
+ NEXT;
+ /* Check for incompleteness. */
+ SKIP_BLANKS;
+ if (CUR == 0) {
+ ERROR5(NULL, NULL, NULL,
+ "Incomplete expression '%s'.\n", ctxt->base);
+ ctxt->error = 1;
+ goto error;
+ }
+ }
+ if (CUR == '@') {
+ NEXT;
+ xmlCompileAttributeTest(ctxt);
+ SKIP_BLANKS;
+ /* TODO: check for incompleteness */
+ if (CUR != 0) {
+ xmlCompileStepPattern(ctxt);
+ if (ctxt->error != 0)
+ goto error;
+ }
+ } else {
+ if (CUR == '/') {
+ PUSH(XML_OP_ROOT, NULL, NULL);
+ NEXT;
+ /* Check for incompleteness. */
+ SKIP_BLANKS;
+ if (CUR == 0) {
+ ERROR5(NULL, NULL, NULL,
+ "Incomplete expression '%s'.\n", ctxt->base);
+ ctxt->error = 1;
+ goto error;
+ }
+ }
+ xmlCompileStepPattern(ctxt);
+ if (ctxt->error != 0)
+ goto error;
+ SKIP_BLANKS;
+ while (CUR == '/') {
+ if (NXT(1) == '/') {
+ PUSH(XML_OP_ANCESTOR, NULL, NULL);
+ NEXT;
+ NEXT;
+ SKIP_BLANKS;
+ xmlCompileStepPattern(ctxt);
+ if (ctxt->error != 0)
+ goto error;
+ } else {
+ PUSH(XML_OP_PARENT, NULL, NULL);
+ NEXT;
+ SKIP_BLANKS;
+ if (CUR == 0) {
+ ERROR5(NULL, NULL, NULL,
+ "Incomplete expression '%s'.\n", ctxt->base);
+ ctxt->error = 1;
+ goto error;
+ }
+ xmlCompileStepPattern(ctxt);
+ if (ctxt->error != 0)
+ goto error;
+ }
+ }
+ }
+ if (CUR != 0) {
+ ERROR5(NULL, NULL, NULL,
+ "Failed to compile pattern %s\n", ctxt->base);
+ ctxt->error = 1;
+ }
+error:
+ return;
+}
+
+/**
+ * xmlCompileIDCXPathPath:
+ * @ctxt: the compilation context
+ *
+ * Compile the Path Pattern and generates a precompiled
+ * form suitable for fast matching.
+ *
+ * [5] Path ::= ('.//')? ( Step '/' )* ( Step | '@' NameTest )
+ */
+static void
+xmlCompileIDCXPathPath(xmlPatParserContextPtr ctxt) {
+ SKIP_BLANKS;
+ if (CUR == '/') {
+ ERROR5(NULL, NULL, NULL,
+ "Unexpected selection of the document root in '%s'.\n",
+ ctxt->base);
+ goto error;
+ }
+ ctxt->comp->flags |= PAT_FROM_CUR;
+
+ if (CUR == '.') {
+ /* "." - "self::node()" */
+ NEXT;
+ SKIP_BLANKS;
+ if (CUR == 0) {
+ /*
+ * Selection of the context node.
+ */
+ PUSH(XML_OP_ELEM, NULL, NULL);
+ return;
+ }
+ if (CUR != '/') {
+ /* TODO: A more meaningful error message. */
+ ERROR5(NULL, NULL, NULL,
+ "Unexpected token after '.' in '%s'.\n", ctxt->base);
+ goto error;
+ }
+ /* "./" - "self::node()/" */
+ NEXT;
+ SKIP_BLANKS;
+ if (CUR == '/') {
+ if (IS_BLANK_CH(PEEKPREV(1))) {
+ /*
+ * Disallow "./ /"
+ */
+ ERROR5(NULL, NULL, NULL,
+ "Unexpected '/' token in '%s'.\n", ctxt->base);
+ goto error;
+ }
+ /* ".//" - "self:node()/descendant-or-self::node()/" */
+ PUSH(XML_OP_ANCESTOR, NULL, NULL);
+ NEXT;
+ SKIP_BLANKS;
+ }
+ if (CUR == 0)
+ goto error_unfinished;
+ }
+ /*
+ * Process steps.
+ */
+ do {
+ xmlCompileStepPattern(ctxt);
+ if (ctxt->error != 0)
+ goto error;
+ SKIP_BLANKS;
+ if (CUR != '/')
+ break;
+ PUSH(XML_OP_PARENT, NULL, NULL);
+ NEXT;
+ SKIP_BLANKS;
+ if (CUR == '/') {
+ /*
+ * Disallow subsequent '//'.
+ */
+ ERROR5(NULL, NULL, NULL,
+ "Unexpected subsequent '//' in '%s'.\n",
+ ctxt->base);
+ goto error;
+ }
+ if (CUR == 0)
+ goto error_unfinished;
+
+ } while (CUR != 0);
+
+ if (CUR != 0) {
+ ERROR5(NULL, NULL, NULL,
+ "Failed to compile expression '%s'.\n", ctxt->base);
+ ctxt->error = 1;
+ }
+ return;
+error:
+ ctxt->error = 1;
+ return;
+
+error_unfinished:
+ ctxt->error = 1;
+ ERROR5(NULL, NULL, NULL,
+ "Unfinished expression '%s'.\n", ctxt->base);
+ return;
+}
+
+/************************************************************************
+ * *
+ * The streaming code *
+ * *
+ ************************************************************************/
+
+#ifdef DEBUG_STREAMING
+static void
+xmlDebugStreamComp(xmlStreamCompPtr stream) {
+ int i;
+
+ if (stream == NULL) {
+ printf("Stream: NULL\n");
+ return;
+ }
+ printf("Stream: %d steps\n", stream->nbStep);
+ for (i = 0;i < stream->nbStep;i++) {
+ if (stream->steps[i].ns != NULL) {
+ printf("{%s}", stream->steps[i].ns);
+ }
+ if (stream->steps[i].name == NULL) {
+ printf("* ");
+ } else {
+ printf("%s ", stream->steps[i].name);
+ }
+ if (stream->steps[i].flags & XML_STREAM_STEP_ROOT)
+ printf("root ");
+ if (stream->steps[i].flags & XML_STREAM_STEP_DESC)
+ printf("// ");
+ if (stream->steps[i].flags & XML_STREAM_STEP_FINAL)
+ printf("final ");
+ printf("\n");
+ }
+}
+static void
+xmlDebugStreamCtxt(xmlStreamCtxtPtr ctxt, int match) {
+ int i;
+
+ if (ctxt == NULL) {
+ printf("Stream: NULL\n");
+ return;
+ }
+ printf("Stream: level %d, %d states: ", ctxt->level, ctxt->nbState);
+ if (match)
+ printf("matches\n");
+ else
+ printf("\n");
+ for (i = 0;i < ctxt->nbState;i++) {
+ if (ctxt->states[2 * i] < 0)
+ printf(" %d: free\n", i);
+ else {
+ printf(" %d: step %d, level %d", i, ctxt->states[2 * i],
+ ctxt->states[(2 * i) + 1]);
+ if (ctxt->comp->steps[ctxt->states[2 * i]].flags &
+ XML_STREAM_STEP_DESC)
+ printf(" //\n");
+ else
+ printf("\n");
+ }
+ }
+}
+#endif
+/**
+ * xmlNewStreamComp:
+ * @size: the number of expected steps
+ *
+ * build a new compiled pattern for streaming
+ *
+ * Returns the new structure or NULL in case of error.
+ */
+static xmlStreamCompPtr
+xmlNewStreamComp(int size) {
+ xmlStreamCompPtr cur;
+
+ if (size < 4)
+ size = 4;
+
+ cur = (xmlStreamCompPtr) xmlMalloc(sizeof(xmlStreamComp));
+ if (cur == NULL) {
+ ERROR(NULL, NULL, NULL,
+ "xmlNewStreamComp: malloc failed\n");
+ return(NULL);
+ }
+ memset(cur, 0, sizeof(xmlStreamComp));
+ cur->steps = (xmlStreamStepPtr) xmlMalloc(size * sizeof(xmlStreamStep));
+ if (cur->steps == NULL) {
+ xmlFree(cur);
+ ERROR(NULL, NULL, NULL,
+ "xmlNewStreamComp: malloc failed\n");
+ return(NULL);
+ }
+ cur->nbStep = 0;
+ cur->maxStep = size;
+ return(cur);
+}
+
+/**
+ * xmlFreeStreamComp:
+ * @comp: the compiled pattern for streaming
+ *
+ * Free the compiled pattern for streaming
+ */
+static void
+xmlFreeStreamComp(xmlStreamCompPtr comp) {
+ if (comp != NULL) {
+ if (comp->steps != NULL)
+ xmlFree(comp->steps);
+ if (comp->dict != NULL)
+ xmlDictFree(comp->dict);
+ xmlFree(comp);
+ }
+}
+
+/**
+ * xmlStreamCompAddStep:
+ * @comp: the compiled pattern for streaming
+ * @name: the first string, the name, or NULL for *
+ * @ns: the second step, the namespace name
+ * @flags: the flags for that step
+ *
+ * Add a new step to the compiled pattern
+ *
+ * Returns -1 in case of error or the step index if successful
+ */
+static int
+xmlStreamCompAddStep(xmlStreamCompPtr comp, const xmlChar *name,
+ const xmlChar *ns, int nodeType, int flags) {
+ xmlStreamStepPtr cur;
+
+ if (comp->nbStep >= comp->maxStep) {
+ cur = (xmlStreamStepPtr) xmlRealloc(comp->steps,
+ comp->maxStep * 2 * sizeof(xmlStreamStep));
+ if (cur == NULL) {
+ ERROR(NULL, NULL, NULL,
+ "xmlNewStreamComp: malloc failed\n");
+ return(-1);
+ }
+ comp->steps = cur;
+ comp->maxStep *= 2;
+ }
+ cur = &comp->steps[comp->nbStep++];
+ cur->flags = flags;
+ cur->name = name;
+ cur->ns = ns;
+ cur->nodeType = nodeType;
+ return(comp->nbStep - 1);
+}
+
+/**
+ * xmlStreamCompile:
+ * @comp: the precompiled pattern
+ *
+ * Tries to stream compile a pattern
+ *
+ * Returns -1 in case of failure and 0 in case of success.
+ */
+static int
+xmlStreamCompile(xmlPatternPtr comp) {
+ xmlStreamCompPtr stream;
+ int i, s = 0, root = 0, flags = 0, prevs = -1;
+ xmlStepOp step;
+
+ if ((comp == NULL) || (comp->steps == NULL))
+ return(-1);
+ /*
+ * special case for .
+ */
+ if ((comp->nbStep == 1) &&
+ (comp->steps[0].op == XML_OP_ELEM) &&
+ (comp->steps[0].value == NULL) &&
+ (comp->steps[0].value2 == NULL)) {
+ stream = xmlNewStreamComp(0);
+ if (stream == NULL)
+ return(-1);
+ /* Note that the stream will have no steps in this case. */
+ stream->flags |= XML_STREAM_FINAL_IS_ANY_NODE;
+ comp->stream = stream;
+ return(0);
+ }
+
+ stream = xmlNewStreamComp((comp->nbStep / 2) + 1);
+ if (stream == NULL)
+ return(-1);
+ if (comp->dict != NULL) {
+ stream->dict = comp->dict;
+ xmlDictReference(stream->dict);
+ }
+
+ i = 0;
+ if (comp->flags & PAT_FROM_ROOT)
+ stream->flags |= XML_STREAM_FROM_ROOT;
+
+ for (;i < comp->nbStep;i++) {
+ step = comp->steps[i];
+ switch (step.op) {
+ case XML_OP_END:
+ break;
+ case XML_OP_ROOT:
+ if (i != 0)
+ goto error;
+ root = 1;
+ break;
+ case XML_OP_NS:
+ s = xmlStreamCompAddStep(stream, NULL, step.value,
+ XML_ELEMENT_NODE, flags);
+ if (s < 0)
+ goto error;
+ prevs = s;
+ flags = 0;
+ break;
+ case XML_OP_ATTR:
+ flags |= XML_STREAM_STEP_ATTR;
+ prevs = -1;
+ s = xmlStreamCompAddStep(stream,
+ step.value, step.value2, XML_ATTRIBUTE_NODE, flags);
+ flags = 0;
+ if (s < 0)
+ goto error;
+ break;
+ case XML_OP_ELEM:
+ if ((step.value == NULL) && (step.value2 == NULL)) {
+ /*
+ * We have a "." or "self::node()" here.
+ * Eliminate redundant self::node() tests like in "/./."
+ * or "//./"
+ * The only case we won't eliminate is "//.", i.e. if
+ * self::node() is the last node test and we had
+ * continuation somewhere beforehand.
+ */
+ if ((comp->nbStep == i + 1) &&
+ (flags & XML_STREAM_STEP_DESC)) {
+ /*
+ * Mark the special case where the expression resolves
+ * to any type of node.
+ */
+ if (comp->nbStep == i + 1) {
+ stream->flags |= XML_STREAM_FINAL_IS_ANY_NODE;
+ }
+ flags |= XML_STREAM_STEP_NODE;
+ s = xmlStreamCompAddStep(stream, NULL, NULL,
+ XML_STREAM_ANY_NODE, flags);
+ if (s < 0)
+ goto error;
+ flags = 0;
+ /*
+ * If there was a previous step, mark it to be added to
+ * the result node-set; this is needed since only
+ * the last step will be marked as "final" and only
+ * "final" nodes are added to the resulting set.
+ */
+ if (prevs != -1) {
+ stream->steps[prevs].flags |= XML_STREAM_STEP_IN_SET;
+ prevs = -1;
+ }
+ break;
+
+ } else {
+ /* Just skip this one. */
+ continue;
+ }
+ }
+ /* An element node. */
+ s = xmlStreamCompAddStep(stream, step.value, step.value2,
+ XML_ELEMENT_NODE, flags);
+ if (s < 0)
+ goto error;
+ prevs = s;
+ flags = 0;
+ break;
+ case XML_OP_CHILD:
+ /* An element node child. */
+ s = xmlStreamCompAddStep(stream, step.value, step.value2,
+ XML_ELEMENT_NODE, flags);
+ if (s < 0)
+ goto error;
+ prevs = s;
+ flags = 0;
+ break;
+ case XML_OP_ALL:
+ s = xmlStreamCompAddStep(stream, NULL, NULL,
+ XML_ELEMENT_NODE, flags);
+ if (s < 0)
+ goto error;
+ prevs = s;
+ flags = 0;
+ break;
+ case XML_OP_PARENT:
+ break;
+ case XML_OP_ANCESTOR:
+ /* Skip redundant continuations. */
+ if (flags & XML_STREAM_STEP_DESC)
+ break;
+ flags |= XML_STREAM_STEP_DESC;
+ /*
+ * Mark the expression as having "//".
+ */
+ if ((stream->flags & XML_STREAM_DESC) == 0)
+ stream->flags |= XML_STREAM_DESC;
+ break;
+ }
+ }
+ if ((! root) && (comp->flags & XML_PATTERN_NOTPATTERN) == 0) {
+ /*
+ * If this should behave like a real pattern, we will mark
+ * the first step as having "//", to be reentrant on every
+ * tree level.
+ */
+ if ((stream->flags & XML_STREAM_DESC) == 0)
+ stream->flags |= XML_STREAM_DESC;
+
+ if (stream->nbStep > 0) {
+ if ((stream->steps[0].flags & XML_STREAM_STEP_DESC) == 0)
+ stream->steps[0].flags |= XML_STREAM_STEP_DESC;
+ }
+ }
+ if (stream->nbStep <= s)
+ goto error;
+ stream->steps[s].flags |= XML_STREAM_STEP_FINAL;
+ if (root)
+ stream->steps[0].flags |= XML_STREAM_STEP_ROOT;
+#ifdef DEBUG_STREAMING
+ xmlDebugStreamComp(stream);
+#endif
+ comp->stream = stream;
+ return(0);
+error:
+ xmlFreeStreamComp(stream);
+ return(0);
+}
+
+/**
+ * xmlNewStreamCtxt:
+ * @size: the number of expected states
+ *
+ * build a new stream context
+ *
+ * Returns the new structure or NULL in case of error.
+ */
+static xmlStreamCtxtPtr
+xmlNewStreamCtxt(xmlStreamCompPtr stream) {
+ xmlStreamCtxtPtr cur;
+
+ cur = (xmlStreamCtxtPtr) xmlMalloc(sizeof(xmlStreamCtxt));
+ if (cur == NULL) {
+ ERROR(NULL, NULL, NULL,
+ "xmlNewStreamCtxt: malloc failed\n");
+ return(NULL);
+ }
+ memset(cur, 0, sizeof(xmlStreamCtxt));
+ cur->states = (int *) xmlMalloc(4 * 2 * sizeof(int));
+ if (cur->states == NULL) {
+ xmlFree(cur);
+ ERROR(NULL, NULL, NULL,
+ "xmlNewStreamCtxt: malloc failed\n");
+ return(NULL);
+ }
+ cur->nbState = 0;
+ cur->maxState = 4;
+ cur->level = 0;
+ cur->comp = stream;
+ cur->blockLevel = -1;
+ return(cur);
+}
+
+/**
+ * xmlFreeStreamCtxt:
+ * @stream: the stream context
+ *
+ * Free the stream context
+ */
+void
+xmlFreeStreamCtxt(xmlStreamCtxtPtr stream) {
+ xmlStreamCtxtPtr next;
+
+ while (stream != NULL) {
+ next = stream->next;
+ if (stream->states != NULL)
+ xmlFree(stream->states);
+ xmlFree(stream);
+ stream = next;
+ }
+}
+
+/**
+ * xmlStreamCtxtAddState:
+ * @comp: the stream context
+ * @idx: the step index for that streaming state
+ *
+ * Add a new state to the stream context
+ *
+ * Returns -1 in case of error or the state index if successful
+ */
+static int
+xmlStreamCtxtAddState(xmlStreamCtxtPtr comp, int idx, int level) {
+ int i;
+ for (i = 0;i < comp->nbState;i++) {
+ if (comp->states[2 * i] < 0) {
+ comp->states[2 * i] = idx;
+ comp->states[2 * i + 1] = level;
+ return(i);
+ }
+ }
+ if (comp->nbState >= comp->maxState) {
+ int *cur;
+
+ cur = (int *) xmlRealloc(comp->states,
+ comp->maxState * 4 * sizeof(int));
+ if (cur == NULL) {
+ ERROR(NULL, NULL, NULL,
+ "xmlNewStreamCtxt: malloc failed\n");
+ return(-1);
+ }
+ comp->states = cur;
+ comp->maxState *= 2;
+ }
+ comp->states[2 * comp->nbState] = idx;
+ comp->states[2 * comp->nbState++ + 1] = level;
+ return(comp->nbState - 1);
+}
+
+/**
+ * xmlStreamPushInternal:
+ * @stream: the stream context
+ * @name: the current name
+ * @ns: the namespace name
+ * @nodeType: the type of the node
+ *
+ * Push new data onto the stream. NOTE: if the call xmlPatterncompile()
+ * indicated a dictionary, then strings for name and ns will be expected
+ * to come from the dictionary.
+ * Both @name and @ns being NULL means the / i.e. the root of the document.
+ * This can also act as a reset.
+ *
+ * Returns: -1 in case of error, 1 if the current state in the stream is a
+ * match and 0 otherwise.
+ */
+static int
+xmlStreamPushInternal(xmlStreamCtxtPtr stream,
+ const xmlChar *name, const xmlChar *ns,
+ int nodeType) {
+ int ret = 0, err = 0, final = 0, tmp, i, m, match, stepNr, desc;
+ xmlStreamCompPtr comp;
+ xmlStreamStep step;
+#ifdef DEBUG_STREAMING
+ xmlStreamCtxtPtr orig = stream;
+#endif
+
+ if ((stream == NULL) || (stream->nbState < 0))
+ return(-1);
+
+ while (stream != NULL) {
+ comp = stream->comp;
+
+ if ((nodeType == XML_ELEMENT_NODE) &&
+ (name == NULL) && (ns == NULL)) {
+ /* We have a document node here (or a reset). */
+ stream->nbState = 0;
+ stream->level = 0;
+ stream->blockLevel = -1;
+ if (comp->flags & XML_STREAM_FROM_ROOT) {
+ if (comp->nbStep == 0) {
+ /* TODO: We have a "/." here? */
+ ret = 1;
+ } else {
+ if ((comp->nbStep == 1) &&
+ (comp->steps[0].nodeType == XML_STREAM_ANY_NODE) &&
+ (comp->steps[0].flags & XML_STREAM_STEP_DESC))
+ {
+ /*
+ * In the case of "//." the document node will match
+ * as well.
+ */
+ ret = 1;
+ } else if (comp->steps[0].flags & XML_STREAM_STEP_ROOT) {
+ /* TODO: Do we need this ? */
+ tmp = xmlStreamCtxtAddState(stream, 0, 0);
+ if (tmp < 0)
+ err++;
+ }
+ }
+ }
+ stream = stream->next;
+ continue; /* while */
+ }
+
+ /*
+ * Fast check for ".".
+ */
+ if (comp->nbStep == 0) {
+ /*
+ * / and . are handled at the XPath node set creation
+ * level by checking min depth
+ */
+ if (stream->flags & XML_PATTERN_XPATH) {
+ stream = stream->next;
+ continue; /* while */
+ }
+ /*
+ * For non-pattern like evaluation like XML Schema IDCs
+ * or traditional XPath expressions, this will match if
+ * we are at the first level only, otherwise on every level.
+ */
+ if ((nodeType != XML_ATTRIBUTE_NODE) &&
+ (((stream->flags & XML_PATTERN_NOTPATTERN) == 0) ||
+ (stream->level == 0))) {
+ ret = 1;
+ }
+ stream->level++;
+ goto stream_next;
+ }
+ if (stream->blockLevel != -1) {
+ /*
+ * Skip blocked expressions.
+ */
+ stream->level++;
+ goto stream_next;
+ }
+
+ if ((nodeType != XML_ELEMENT_NODE) &&
+ (nodeType != XML_ATTRIBUTE_NODE) &&
+ ((comp->flags & XML_STREAM_FINAL_IS_ANY_NODE) == 0)) {
+ /*
+ * No need to process nodes of other types if we don't
+ * resolve to those types.
+ * TODO: Do we need to block the context here?
+ */
+ stream->level++;
+ goto stream_next;
+ }
+
+ /*
+ * Check evolution of existing states
+ */
+ i = 0;
+ m = stream->nbState;
+ while (i < m) {
+ if ((comp->flags & XML_STREAM_DESC) == 0) {
+ /*
+ * If there is no "//", then only the last
+ * added state is of interest.
+ */
+ stepNr = stream->states[2 * (stream->nbState -1)];
+ /*
+ * TODO: Security check, should not happen, remove it.
+ */
+ if (stream->states[(2 * (stream->nbState -1)) + 1] <
+ stream->level) {
+ return (-1);
+ }
+ desc = 0;
+ /* loop-stopper */
+ i = m;
+ } else {
+ /*
+ * If there are "//", then we need to process every "//"
+ * occuring in the states, plus any other state for this
+ * level.
+ */
+ stepNr = stream->states[2 * i];
+
+ /* TODO: should not happen anymore: dead states */
+ if (stepNr < 0)
+ goto next_state;
+
+ tmp = stream->states[(2 * i) + 1];
+
+ /* skip new states just added */
+ if (tmp > stream->level)
+ goto next_state;
+
+ /* skip states at ancestor levels, except if "//" */
+ desc = comp->steps[stepNr].flags & XML_STREAM_STEP_DESC;
+ if ((tmp < stream->level) && (!desc))
+ goto next_state;
+ }
+ /*
+ * Check for correct node-type.
+ */
+ step = comp->steps[stepNr];
+ if (step.nodeType != nodeType) {
+ if (step.nodeType == XML_ATTRIBUTE_NODE) {
+ /*
+ * Block this expression for deeper evaluation.
+ */
+ if ((comp->flags & XML_STREAM_DESC) == 0)
+ stream->blockLevel = stream->level +1;
+ goto next_state;
+ } else if (step.nodeType != XML_STREAM_ANY_NODE)
+ goto next_state;
+ }
+ /*
+ * Compare local/namespace-name.
+ */
+ match = 0;
+ if (step.nodeType == XML_STREAM_ANY_NODE) {
+ match = 1;
+ } else if (step.name == NULL) {
+ if (step.ns == NULL) {
+ /*
+ * This lets through all elements/attributes.
+ */
+ match = 1;
+ } else if (ns != NULL)
+ match = xmlStrEqual(step.ns, ns);
+ } else if (((step.ns != NULL) == (ns != NULL)) &&
+ (name != NULL) &&
+ (step.name[0] == name[0]) &&
+ xmlStrEqual(step.name, name) &&
+ ((step.ns == ns) || xmlStrEqual(step.ns, ns)))
+ {
+ match = 1;
+ }
+#if 0
+/*
+* TODO: Pointer comparison won't work, since not guaranteed that the given
+* values are in the same dict; especially if it's the namespace name,
+* normally coming from ns->href. We need a namespace dict mechanism !
+*/
+ } else if (comp->dict) {
+ if (step.name == NULL) {
+ if (step.ns == NULL)
+ match = 1;
+ else
+ match = (step.ns == ns);
+ } else {
+ match = ((step.name == name) && (step.ns == ns));
+ }
+#endif /* if 0 ------------------------------------------------------- */
+ if (match) {
+ final = step.flags & XML_STREAM_STEP_FINAL;
+ if (desc) {
+ if (final) {
+ ret = 1;
+ } else {
+ /* descending match create a new state */
+ xmlStreamCtxtAddState(stream, stepNr + 1,
+ stream->level + 1);
+ }
+ } else {
+ if (final) {
+ ret = 1;
+ } else {
+ xmlStreamCtxtAddState(stream, stepNr + 1,
+ stream->level + 1);
+ }
+ }
+ if ((ret != 1) && (step.flags & XML_STREAM_STEP_IN_SET)) {
+ /*
+ * Check if we have a special case like "foo/bar//.", where
+ * "foo" is selected as well.
+ */
+ ret = 1;
+ }
+ }
+ if (((comp->flags & XML_STREAM_DESC) == 0) &&
+ ((! match) || final)) {
+ /*
+ * Mark this expression as blocked for any evaluation at
+ * deeper levels. Note that this includes "/foo"
+ * expressions if the *pattern* behaviour is used.
+ */
+ stream->blockLevel = stream->level +1;
+ }
+next_state:
+ i++;
+ }
+
+ stream->level++;
+
+ /*
+ * Re/enter the expression.
+ * Don't reenter if it's an absolute expression like "/foo",
+ * except "//foo".
+ */
+ step = comp->steps[0];
+ if (step.flags & XML_STREAM_STEP_ROOT)
+ goto stream_next;
+
+ desc = step.flags & XML_STREAM_STEP_DESC;
+ if (stream->flags & XML_PATTERN_NOTPATTERN) {
+ /*
+ * Re/enter the expression if it is a "descendant" one,
+ * or if we are at the 1st level of evaluation.
+ */
+
+ if (stream->level == 1) {
+ if (XML_STREAM_XS_IDC(stream)) {
+ /*
+ * XS-IDC: The missing "self::node()" will always
+ * match the first given node.
+ */
+ goto stream_next;
+ } else
+ goto compare;
+ }
+ /*
+ * A "//" is always reentrant.
+ */
+ if (desc)
+ goto compare;
+
+ /*
+ * XS-IDC: Process the 2nd level, since the missing
+ * "self::node()" is responsible for the 2nd level being
+ * the real start level.
+ */
+ if ((stream->level == 2) && XML_STREAM_XS_IDC(stream))
+ goto compare;
+
+ goto stream_next;
+ }
+
+compare:
+ /*
+ * Check expected node-type.
+ */
+ if (step.nodeType != nodeType) {
+ if (nodeType == XML_ATTRIBUTE_NODE)
+ goto stream_next;
+ else if (step.nodeType != XML_STREAM_ANY_NODE)
+ goto stream_next;
+ }
+ /*
+ * Compare local/namespace-name.
+ */
+ match = 0;
+ if (step.nodeType == XML_STREAM_ANY_NODE) {
+ match = 1;
+ } else if (step.name == NULL) {
+ if (step.ns == NULL) {
+ /*
+ * This lets through all elements/attributes.
+ */
+ match = 1;
+ } else if (ns != NULL)
+ match = xmlStrEqual(step.ns, ns);
+ } else if (((step.ns != NULL) == (ns != NULL)) &&
+ (name != NULL) &&
+ (step.name[0] == name[0]) &&
+ xmlStrEqual(step.name, name) &&
+ ((step.ns == ns) || xmlStrEqual(step.ns, ns)))
+ {
+ match = 1;
+ }
+ final = step.flags & XML_STREAM_STEP_FINAL;
+ if (match) {
+ if (final)
+ ret = 1;
+ else
+ xmlStreamCtxtAddState(stream, 1, stream->level);
+ if ((ret != 1) && (step.flags & XML_STREAM_STEP_IN_SET)) {
+ /*
+ * Check if we have a special case like "foo//.", where
+ * "foo" is selected as well.
+ */
+ ret = 1;
+ }
+ }
+ if (((comp->flags & XML_STREAM_DESC) == 0) &&
+ ((! match) || final)) {
+ /*
+ * Mark this expression as blocked for any evaluation at
+ * deeper levels.
+ */
+ stream->blockLevel = stream->level;
+ }
+
+stream_next:
+ stream = stream->next;
+ } /* while stream != NULL */
+
+ if (err > 0)
+ ret = -1;
+#ifdef DEBUG_STREAMING
+ xmlDebugStreamCtxt(orig, ret);
+#endif
+ return(ret);
+}
+
+/**
+ * xmlStreamPush:
+ * @stream: the stream context
+ * @name: the current name
+ * @ns: the namespace name
+ *
+ * Push new data onto the stream. NOTE: if the call xmlPatterncompile()
+ * indicated a dictionary, then strings for name and ns will be expected
+ * to come from the dictionary.
+ * Both @name and @ns being NULL means the / i.e. the root of the document.
+ * This can also act as a reset.
+ * Otherwise the function will act as if it has been given an element-node.
+ *
+ * Returns: -1 in case of error, 1 if the current state in the stream is a
+ * match and 0 otherwise.
+ */
+int
+xmlStreamPush(xmlStreamCtxtPtr stream,
+ const xmlChar *name, const xmlChar *ns) {
+ return (xmlStreamPushInternal(stream, name, ns, (int) XML_ELEMENT_NODE));
+}
+
+/**
+ * xmlStreamPushNode:
+ * @stream: the stream context
+ * @name: the current name
+ * @ns: the namespace name
+ * @nodeType: the type of the node being pushed
+ *
+ * Push new data onto the stream. NOTE: if the call xmlPatterncompile()
+ * indicated a dictionary, then strings for name and ns will be expected
+ * to come from the dictionary.
+ * Both @name and @ns being NULL means the / i.e. the root of the document.
+ * This can also act as a reset.
+ * Different from xmlStreamPush() this function can be fed with nodes of type:
+ * element-, attribute-, text-, cdata-section-, comment- and
+ * processing-instruction-node.
+ *
+ * Returns: -1 in case of error, 1 if the current state in the stream is a
+ * match and 0 otherwise.
+ */
+int
+xmlStreamPushNode(xmlStreamCtxtPtr stream,
+ const xmlChar *name, const xmlChar *ns,
+ int nodeType)
+{
+ return (xmlStreamPushInternal(stream, name, ns,
+ nodeType));
+}
+
+/**
+* xmlStreamPushAttr:
+* @stream: the stream context
+* @name: the current name
+* @ns: the namespace name
+*
+* Push new attribute data onto the stream. NOTE: if the call xmlPatterncompile()
+* indicated a dictionary, then strings for name and ns will be expected
+* to come from the dictionary.
+* Both @name and @ns being NULL means the / i.e. the root of the document.
+* This can also act as a reset.
+* Otherwise the function will act as if it has been given an attribute-node.
+*
+* Returns: -1 in case of error, 1 if the current state in the stream is a
+* match and 0 otherwise.
+*/
+int
+xmlStreamPushAttr(xmlStreamCtxtPtr stream,
+ const xmlChar *name, const xmlChar *ns) {
+ return (xmlStreamPushInternal(stream, name, ns, (int) XML_ATTRIBUTE_NODE));
+}
+
+/**
+ * xmlStreamPop:
+ * @stream: the stream context
+ *
+ * push one level from the stream.
+ *
+ * Returns: -1 in case of error, 0 otherwise.
+ */
+int
+xmlStreamPop(xmlStreamCtxtPtr stream) {
+ int i, lev;
+
+ if (stream == NULL)
+ return(-1);
+ while (stream != NULL) {
+ /*
+ * Reset block-level.
+ */
+ if (stream->blockLevel == stream->level)
+ stream->blockLevel = -1;
+
+ stream->level--;
+ if (stream->level < 0)
+ return(-1);
+ /*
+ * Check evolution of existing states
+ */
+ for (i = stream->nbState -1; i >= 0; i--) {
+ /* discard obsoleted states */
+ lev = stream->states[(2 * i) + 1];
+ if (lev > stream->level)
+ stream->nbState--;
+ if (lev <= stream->level)
+ break;
+ }
+ stream = stream->next;
+ }
+ return(0);
+}
+
+/**
+ * xmlStreamWantsAnyNode:
+ * @streamCtxt: the stream context
+ *
+ * Query if the streaming pattern additionally needs to be fed with
+ * text-, cdata-section-, comment- and processing-instruction-nodes.
+ * If the result is 0 then only element-nodes and attribute-nodes
+ * need to be pushed.
+ *
+ * Returns: 1 in case of need of nodes of the above described types,
+ * 0 otherwise. -1 on API errors.
+ */
+int
+xmlStreamWantsAnyNode(xmlStreamCtxtPtr streamCtxt)
+{
+ if (streamCtxt == NULL)
+ return(-1);
+ while (streamCtxt != NULL) {
+ if (streamCtxt->comp->flags & XML_STREAM_FINAL_IS_ANY_NODE)
+ return(1);
+ streamCtxt = streamCtxt->next;
+ }
+ return(0);
+}
+
+/************************************************************************
+ * *
+ * The public interfaces *
+ * *
+ ************************************************************************/
+
+/**
+ * xmlPatterncompile:
+ * @pattern: the pattern to compile
+ * @dict: an optional dictionary for interned strings
+ * @flags: compilation flags, see xmlPatternFlags
+ * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
+ *
+ * Compile a pattern.
+ *
+ * Returns the compiled form of the pattern or NULL in case of error
+ */
+xmlPatternPtr
+xmlPatterncompile(const xmlChar *pattern, xmlDict *dict, int flags,
+ const xmlChar **namespaces) {
+ xmlPatternPtr ret = NULL, cur;
+ xmlPatParserContextPtr ctxt = NULL;
+ const xmlChar *or, *start;
+ xmlChar *tmp = NULL;
+ int type = 0;
+ int streamable = 1;
+
+ if (pattern == NULL)
+ return(NULL);
+
+ start = pattern;
+ or = start;
+ while (*or != 0) {
+ tmp = NULL;
+ while ((*or != 0) && (*or != '|')) or++;
+ if (*or == 0)
+ ctxt = xmlNewPatParserContext(start, dict, namespaces);
+ else {
+ tmp = xmlStrndup(start, or - start);
+ if (tmp != NULL) {
+ ctxt = xmlNewPatParserContext(tmp, dict, namespaces);
+ }
+ or++;
+ }
+ if (ctxt == NULL) goto error;
+ cur = xmlNewPattern();
+ if (cur == NULL) goto error;
+ /*
+ * Assign string dict.
+ */
+ if (dict) {
+ cur->dict = dict;
+ xmlDictReference(dict);
+ }
+ if (ret == NULL)
+ ret = cur;
+ else {
+ cur->next = ret->next;
+ ret->next = cur;
+ }
+ cur->flags = flags;
+ ctxt->comp = cur;
+
+ if (XML_STREAM_XS_IDC(cur))
+ xmlCompileIDCXPathPath(ctxt);
+ else
+ xmlCompilePathPattern(ctxt);
+ if (ctxt->error != 0)
+ goto error;
+ xmlFreePatParserContext(ctxt);
+ ctxt = NULL;
+
+
+ if (streamable) {
+ if (type == 0) {
+ type = cur->flags & (PAT_FROM_ROOT | PAT_FROM_CUR);
+ } else if (type == PAT_FROM_ROOT) {
+ if (cur->flags & PAT_FROM_CUR)
+ streamable = 0;
+ } else if (type == PAT_FROM_CUR) {
+ if (cur->flags & PAT_FROM_ROOT)
+ streamable = 0;
+ }
+ }
+ if (streamable)
+ xmlStreamCompile(cur);
+ if (xmlReversePattern(cur) < 0)
+ goto error;
+ if (tmp != NULL) {
+ xmlFree(tmp);
+ tmp = NULL;
+ }
+ start = or;
+ }
+ if (streamable == 0) {
+ cur = ret;
+ while (cur != NULL) {
+ if (cur->stream != NULL) {
+ xmlFreeStreamComp(cur->stream);
+ cur->stream = NULL;
+ }
+ cur = cur->next;
+ }
+ }
+
+ return(ret);
+error:
+ if (ctxt != NULL) xmlFreePatParserContext(ctxt);
+ if (ret != NULL) xmlFreePattern(ret);
+ if (tmp != NULL) xmlFree(tmp);
+ return(NULL);
+}
+
+/**
+ * xmlPatternMatch:
+ * @comp: the precompiled pattern
+ * @node: a node
+ *
+ * Test whether the node matches the pattern
+ *
+ * Returns 1 if it matches, 0 if it doesn't and -1 in case of failure
+ */
+int
+xmlPatternMatch(xmlPatternPtr comp, xmlNodePtr node)
+{
+ int ret = 0;
+
+ if ((comp == NULL) || (node == NULL))
+ return(-1);
+
+ while (comp != NULL) {
+ ret = xmlPatMatch(comp, node);
+ if (ret != 0)
+ return(ret);
+ comp = comp->next;
+ }
+ return(ret);
+}
+
+/**
+ * xmlPatternGetStreamCtxt:
+ * @comp: the precompiled pattern
+ *
+ * Get a streaming context for that pattern
+ * Use xmlFreeStreamCtxt to free the context.
+ *
+ * Returns a pointer to the context or NULL in case of failure
+ */
+xmlStreamCtxtPtr
+xmlPatternGetStreamCtxt(xmlPatternPtr comp)
+{
+ xmlStreamCtxtPtr ret = NULL, cur;
+
+ if ((comp == NULL) || (comp->stream == NULL))
+ return(NULL);
+
+ while (comp != NULL) {
+ if (comp->stream == NULL)
+ goto failed;
+ cur = xmlNewStreamCtxt(comp->stream);
+ if (cur == NULL)
+ goto failed;
+ if (ret == NULL)
+ ret = cur;
+ else {
+ cur->next = ret->next;
+ ret->next = cur;
+ }
+ cur->flags = comp->flags;
+ comp = comp->next;
+ }
+ return(ret);
+failed:
+ xmlFreeStreamCtxt(ret);
+ return(NULL);
+}
+
+/**
+ * xmlPatternStreamable:
+ * @comp: the precompiled pattern
+ *
+ * Check if the pattern is streamable i.e. xmlPatternGetStreamCtxt()
+ * should work.
+ *
+ * Returns 1 if streamable, 0 if not and -1 in case of error.
+ */
+int
+xmlPatternStreamable(xmlPatternPtr comp) {
+ if (comp == NULL)
+ return(-1);
+ while (comp != NULL) {
+ if (comp->stream == NULL)
+ return(0);
+ comp = comp->next;
+ }
+ return(1);
+}
+
+/**
+ * xmlPatternMaxDepth:
+ * @comp: the precompiled pattern
+ *
+ * Check the maximum depth reachable by a pattern
+ *
+ * Returns -2 if no limit (using //), otherwise the depth,
+ * and -1 in case of error
+ */
+int
+xmlPatternMaxDepth(xmlPatternPtr comp) {
+ int ret = 0, i;
+ if (comp == NULL)
+ return(-1);
+ while (comp != NULL) {
+ if (comp->stream == NULL)
+ return(-1);
+ for (i = 0;i < comp->stream->nbStep;i++)
+ if (comp->stream->steps[i].flags & XML_STREAM_STEP_DESC)
+ return(-2);
+ if (comp->stream->nbStep > ret)
+ ret = comp->stream->nbStep;
+ comp = comp->next;
+ }
+ return(ret);
+}
+
+/**
+ * xmlPatternMinDepth:
+ * @comp: the precompiled pattern
+ *
+ * Check the minimum depth reachable by a pattern, 0 mean the / or . are
+ * part of the set.
+ *
+ * Returns -1 in case of error otherwise the depth,
+ *
+ */
+int
+xmlPatternMinDepth(xmlPatternPtr comp) {
+ int ret = 12345678;
+ if (comp == NULL)
+ return(-1);
+ while (comp != NULL) {
+ if (comp->stream == NULL)
+ return(-1);
+ if (comp->stream->nbStep < ret)
+ ret = comp->stream->nbStep;
+ if (ret == 0)
+ return(0);
+ comp = comp->next;
+ }
+ return(ret);
+}
+
+/**
+ * xmlPatternFromRoot:
+ * @comp: the precompiled pattern
+ *
+ * Check if the pattern must be looked at from the root.
+ *
+ * Returns 1 if true, 0 if false and -1 in case of error
+ */
+int
+xmlPatternFromRoot(xmlPatternPtr comp) {
+ if (comp == NULL)
+ return(-1);
+ while (comp != NULL) {
+ if (comp->stream == NULL)
+ return(-1);
+ if (comp->flags & PAT_FROM_ROOT)
+ return(1);
+ comp = comp->next;
+ }
+ return(0);
+
+}
+
+#define bottom_pattern
+#include "elfgcchack.h"
+#endif /* LIBXML_PATTERN_ENABLED */
diff --git a/gettext-tools/gnulib-lib/libxml/pattern.in.h b/gettext-tools/gnulib-lib/libxml/pattern.in.h
new file mode 100644
index 0000000..97d2cd2
--- /dev/null
+++ b/gettext-tools/gnulib-lib/libxml/pattern.in.h
@@ -0,0 +1,100 @@
+/*
+ * Summary: pattern expression handling
+ * Description: allows to compile and test pattern expressions for nodes
+ * either in a tree or based on a parser state.
+ *
+ * Copy: See Copyright for the status of this software.
+ *
+ * Author: Daniel Veillard
+ */
+
+#ifndef __XML_PATTERN_H__
+#define __XML_PATTERN_H__
+
+#include <libxml/xmlversion.h>
+#include <libxml/tree.h>
+#include <libxml/dict.h>
+
+#ifdef LIBXML_PATTERN_ENABLED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * xmlPattern:
+ *
+ * A compiled (XPath based) pattern to select nodes
+ */
+typedef struct _xmlPattern xmlPattern;
+typedef xmlPattern *xmlPatternPtr;
+
+/**
+ * xmlPatternFlags:
+ *
+ * This is the set of options affecting the behaviour of pattern
+ * matching with this module
+ *
+ */
+typedef enum {
+ XML_PATTERN_DEFAULT = 0, /* simple pattern match */
+ XML_PATTERN_XPATH = 1<<0, /* standard XPath pattern */
+ XML_PATTERN_XSSEL = 1<<1, /* XPath subset for schema selector */
+ XML_PATTERN_XSFIELD = 1<<2 /* XPath subset for schema field */
+} xmlPatternFlags;
+
+XMLPUBFUN void XMLCALL
+ xmlFreePattern (xmlPatternPtr comp);
+
+XMLPUBFUN void XMLCALL
+ xmlFreePatternList (xmlPatternPtr comp);
+
+XMLPUBFUN xmlPatternPtr XMLCALL
+ xmlPatterncompile (const xmlChar *pattern,
+ xmlDict *dict,
+ int flags,
+ const xmlChar **namespaces);
+XMLPUBFUN int XMLCALL
+ xmlPatternMatch (xmlPatternPtr comp,
+ xmlNodePtr node);
+
+/* streaming interfaces */
+typedef struct _xmlStreamCtxt xmlStreamCtxt;
+typedef xmlStreamCtxt *xmlStreamCtxtPtr;
+
+XMLPUBFUN int XMLCALL
+ xmlPatternStreamable (xmlPatternPtr comp);
+XMLPUBFUN int XMLCALL
+ xmlPatternMaxDepth (xmlPatternPtr comp);
+XMLPUBFUN int XMLCALL
+ xmlPatternMinDepth (xmlPatternPtr comp);
+XMLPUBFUN int XMLCALL
+ xmlPatternFromRoot (xmlPatternPtr comp);
+XMLPUBFUN xmlStreamCtxtPtr XMLCALL
+ xmlPatternGetStreamCtxt (xmlPatternPtr comp);
+XMLPUBFUN void XMLCALL
+ xmlFreeStreamCtxt (xmlStreamCtxtPtr stream);
+XMLPUBFUN int XMLCALL
+ xmlStreamPushNode (xmlStreamCtxtPtr stream,
+ const xmlChar *name,
+ const xmlChar *ns,
+ int nodeType);
+XMLPUBFUN int XMLCALL
+ xmlStreamPush (xmlStreamCtxtPtr stream,
+ const xmlChar *name,
+ const xmlChar *ns);
+XMLPUBFUN int XMLCALL
+ xmlStreamPushAttr (xmlStreamCtxtPtr stream,
+ const xmlChar *name,
+ const xmlChar *ns);
+XMLPUBFUN int XMLCALL
+ xmlStreamPop (xmlStreamCtxtPtr stream);
+XMLPUBFUN int XMLCALL
+ xmlStreamWantsAnyNode (xmlStreamCtxtPtr stream);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LIBXML_PATTERN_ENABLED */
+
+#endif /* __XML_PATTERN_H__ */
diff --git a/gettext-tools/gnulib-lib/libxml/relaxng.c b/gettext-tools/gnulib-lib/libxml/relaxng.c
new file mode 100644
index 0000000..16527cc
--- /dev/null
+++ b/gettext-tools/gnulib-lib/libxml/relaxng.c
@@ -0,0 +1,10815 @@
+/*
+ * relaxng.c : implementation of the Relax-NG handling and validity checking
+ *
+ * See Copyright for the status of this software.
+ *
+ * Daniel Veillard <veillard@redhat.com>
+ */
+
+/**
+ * TODO:
+ * - add support for DTD compatibility spec
+ * http://www.oasis-open.org/committees/relax-ng/compatibility-20011203.html
+ * - report better mem allocations pbms at runtime and abort immediately.
+ */
+
+#define IN_LIBXML
+#include "libxml.h"
+
+#ifdef LIBXML_SCHEMAS_ENABLED
+
+#include <string.h>
+#include <stdio.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/hash.h>
+#include <libxml/uri.h>
+
+#include <libxml/relaxng.h>
+
+#include <libxml/xmlschemastypes.h>
+#include <libxml/xmlautomata.h>
+#include <libxml/xmlregexp.h>
+#include <libxml/xmlschemastypes.h>
+
+/*
+ * The Relax-NG namespace
+ */
+static const xmlChar *xmlRelaxNGNs = (const xmlChar *)
+ "http://relaxng.org/ns/structure/1.0";
+
+#define IS_RELAXNG(node, type) \
+ ((node != NULL) && (node->ns != NULL) && \
+ (xmlStrEqual(node->name, (const xmlChar *) type)) && \
+ (xmlStrEqual(node->ns->href, xmlRelaxNGNs)))
+
+
+#if 0
+#define DEBUG 1
+
+#define DEBUG_GRAMMAR 1
+
+#define DEBUG_CONTENT 1
+
+#define DEBUG_TYPE 1
+
+#define DEBUG_VALID 1
+
+#define DEBUG_INTERLEAVE 1
+
+#define DEBUG_LIST 1
+
+#define DEBUG_INCLUDE 1
+
+#define DEBUG_ERROR 1
+
+#define DEBUG_COMPILE 1
+
+#define DEBUG_PROGRESSIVE 1
+#endif
+
+#define MAX_ERROR 5
+
+#define TODO \
+ xmlGenericError(xmlGenericErrorContext, \
+ "Unimplemented block at %s:%d\n", \
+ __FILE__, __LINE__);
+
+typedef struct _xmlRelaxNGSchema xmlRelaxNGSchema;
+typedef xmlRelaxNGSchema *xmlRelaxNGSchemaPtr;
+
+typedef struct _xmlRelaxNGDefine xmlRelaxNGDefine;
+typedef xmlRelaxNGDefine *xmlRelaxNGDefinePtr;
+
+typedef struct _xmlRelaxNGDocument xmlRelaxNGDocument;
+typedef xmlRelaxNGDocument *xmlRelaxNGDocumentPtr;
+
+typedef struct _xmlRelaxNGInclude xmlRelaxNGInclude;
+typedef xmlRelaxNGInclude *xmlRelaxNGIncludePtr;
+
+typedef enum {
+ XML_RELAXNG_COMBINE_UNDEFINED = 0, /* undefined */
+ XML_RELAXNG_COMBINE_CHOICE, /* choice */
+ XML_RELAXNG_COMBINE_INTERLEAVE /* interleave */
+} xmlRelaxNGCombine;
+
+typedef enum {
+ XML_RELAXNG_CONTENT_ERROR = -1,
+ XML_RELAXNG_CONTENT_EMPTY = 0,
+ XML_RELAXNG_CONTENT_SIMPLE,
+ XML_RELAXNG_CONTENT_COMPLEX
+} xmlRelaxNGContentType;
+
+typedef struct _xmlRelaxNGGrammar xmlRelaxNGGrammar;
+typedef xmlRelaxNGGrammar *xmlRelaxNGGrammarPtr;
+
+struct _xmlRelaxNGGrammar {
+ xmlRelaxNGGrammarPtr parent; /* the parent grammar if any */
+ xmlRelaxNGGrammarPtr children; /* the children grammar if any */
+ xmlRelaxNGGrammarPtr next; /* the next grammar if any */
+ xmlRelaxNGDefinePtr start; /* <start> content */
+ xmlRelaxNGCombine combine; /* the default combine value */
+ xmlRelaxNGDefinePtr startList; /* list of <start> definitions */
+ xmlHashTablePtr defs; /* define* */
+ xmlHashTablePtr refs; /* references */
+};
+
+
+typedef enum {
+ XML_RELAXNG_NOOP = -1, /* a no operation from simplification */
+ XML_RELAXNG_EMPTY = 0, /* an empty pattern */
+ XML_RELAXNG_NOT_ALLOWED, /* not allowed top */
+ XML_RELAXNG_EXCEPT, /* except present in nameclass defs */
+ XML_RELAXNG_TEXT, /* textual content */
+ XML_RELAXNG_ELEMENT, /* an element */
+ XML_RELAXNG_DATATYPE, /* extenal data type definition */
+ XML_RELAXNG_PARAM, /* extenal data type parameter */
+ XML_RELAXNG_VALUE, /* value from an extenal data type definition */
+ XML_RELAXNG_LIST, /* a list of patterns */
+ XML_RELAXNG_ATTRIBUTE, /* an attrbute following a pattern */
+ XML_RELAXNG_DEF, /* a definition */
+ XML_RELAXNG_REF, /* reference to a definition */
+ XML_RELAXNG_EXTERNALREF, /* reference to an external def */
+ XML_RELAXNG_PARENTREF, /* reference to a def in the parent grammar */
+ XML_RELAXNG_OPTIONAL, /* optional patterns */
+ XML_RELAXNG_ZEROORMORE, /* zero or more non empty patterns */
+ XML_RELAXNG_ONEORMORE, /* one or more non empty patterns */
+ XML_RELAXNG_CHOICE, /* a choice between non empty patterns */
+ XML_RELAXNG_GROUP, /* a pair/group of non empty patterns */
+ XML_RELAXNG_INTERLEAVE, /* interleaving choice of non-empty patterns */
+ XML_RELAXNG_START /* Used to keep track of starts on grammars */
+} xmlRelaxNGType;
+
+#define IS_NULLABLE (1 << 0)
+#define IS_NOT_NULLABLE (1 << 1)
+#define IS_INDETERMINIST (1 << 2)
+#define IS_MIXED (1 << 3)
+#define IS_TRIABLE (1 << 4)
+#define IS_PROCESSED (1 << 5)
+#define IS_COMPILABLE (1 << 6)
+#define IS_NOT_COMPILABLE (1 << 7)
+
+struct _xmlRelaxNGDefine {
+ xmlRelaxNGType type; /* the type of definition */
+ xmlNodePtr node; /* the node in the source */
+ xmlChar *name; /* the element local name if present */
+ xmlChar *ns; /* the namespace local name if present */
+ xmlChar *value; /* value when available */
+ void *data; /* data lib or specific pointer */
+ xmlRelaxNGDefinePtr content; /* the expected content */
+ xmlRelaxNGDefinePtr parent; /* the parent definition, if any */
+ xmlRelaxNGDefinePtr next; /* list within grouping sequences */
+ xmlRelaxNGDefinePtr attrs; /* list of attributes for elements */
+ xmlRelaxNGDefinePtr nameClass; /* the nameClass definition if any */
+ xmlRelaxNGDefinePtr nextHash; /* next define in defs/refs hash tables */
+ short depth; /* used for the cycle detection */
+ short dflags; /* define related flags */
+ xmlRegexpPtr contModel; /* a compiled content model if available */
+};
+
+/**
+ * _xmlRelaxNG:
+ *
+ * A RelaxNGs definition
+ */
+struct _xmlRelaxNG {
+ void *_private; /* unused by the library for users or bindings */
+ xmlRelaxNGGrammarPtr topgrammar;
+ xmlDocPtr doc;
+
+ int idref; /* requires idref checking */
+
+ xmlHashTablePtr defs; /* define */
+ xmlHashTablePtr refs; /* references */
+ xmlRelaxNGDocumentPtr documents; /* all the documents loaded */
+ xmlRelaxNGIncludePtr includes; /* all the includes loaded */
+ int defNr; /* number of defines used */
+ xmlRelaxNGDefinePtr *defTab; /* pointer to the allocated definitions */
+
+};
+
+#define XML_RELAXNG_IN_ATTRIBUTE (1 << 0)
+#define XML_RELAXNG_IN_ONEORMORE (1 << 1)
+#define XML_RELAXNG_IN_LIST (1 << 2)
+#define XML_RELAXNG_IN_DATAEXCEPT (1 << 3)
+#define XML_RELAXNG_IN_START (1 << 4)
+#define XML_RELAXNG_IN_OOMGROUP (1 << 5)
+#define XML_RELAXNG_IN_OOMINTERLEAVE (1 << 6)
+#define XML_RELAXNG_IN_EXTERNALREF (1 << 7)
+#define XML_RELAXNG_IN_ANYEXCEPT (1 << 8)
+#define XML_RELAXNG_IN_NSEXCEPT (1 << 9)
+
+struct _xmlRelaxNGParserCtxt {
+ void *userData; /* user specific data block */
+ xmlRelaxNGValidityErrorFunc error; /* the callback in case of errors */
+ xmlRelaxNGValidityWarningFunc warning; /* the callback in case of warning */
+ xmlStructuredErrorFunc serror;
+ xmlRelaxNGValidErr err;
+
+ xmlRelaxNGPtr schema; /* The schema in use */
+ xmlRelaxNGGrammarPtr grammar; /* the current grammar */
+ xmlRelaxNGGrammarPtr parentgrammar; /* the parent grammar */
+ int flags; /* parser flags */
+ int nbErrors; /* number of errors at parse time */
+ int nbWarnings; /* number of warnings at parse time */
+ const xmlChar *define; /* the current define scope */
+ xmlRelaxNGDefinePtr def; /* the current define */
+
+ int nbInterleaves;
+ xmlHashTablePtr interleaves; /* keep track of all the interleaves */
+
+ xmlRelaxNGDocumentPtr documents; /* all the documents loaded */
+ xmlRelaxNGIncludePtr includes; /* all the includes loaded */
+ xmlChar *URL;
+ xmlDocPtr document;
+
+ int defNr; /* number of defines used */
+ int defMax; /* number of defines aloocated */
+ xmlRelaxNGDefinePtr *defTab; /* pointer to the allocated definitions */
+
+ const char *buffer;
+ int size;
+
+ /* the document stack */
+ xmlRelaxNGDocumentPtr doc; /* Current parsed external ref */
+ int docNr; /* Depth of the parsing stack */
+ int docMax; /* Max depth of the parsing stack */
+ xmlRelaxNGDocumentPtr *docTab; /* array of docs */
+
+ /* the include stack */
+ xmlRelaxNGIncludePtr inc; /* Current parsed include */
+ int incNr; /* Depth of the include parsing stack */
+ int incMax; /* Max depth of the parsing stack */
+ xmlRelaxNGIncludePtr *incTab; /* array of incs */
+
+ int idref; /* requires idref checking */
+
+ /* used to compile content models */
+ xmlAutomataPtr am; /* the automata */
+ xmlAutomataStatePtr state; /* used to build the automata */
+
+ int crng; /* compact syntax and other flags */
+ int freedoc; /* need to free the document */
+};
+
+#define FLAGS_IGNORABLE 1
+#define FLAGS_NEGATIVE 2
+#define FLAGS_MIXED_CONTENT 4
+#define FLAGS_NOERROR 8
+
+/**
+ * xmlRelaxNGInterleaveGroup:
+ *
+ * A RelaxNGs partition set associated to lists of definitions
+ */
+typedef struct _xmlRelaxNGInterleaveGroup xmlRelaxNGInterleaveGroup;
+typedef xmlRelaxNGInterleaveGroup *xmlRelaxNGInterleaveGroupPtr;
+struct _xmlRelaxNGInterleaveGroup {
+ xmlRelaxNGDefinePtr rule; /* the rule to satisfy */
+ xmlRelaxNGDefinePtr *defs; /* the array of element definitions */
+ xmlRelaxNGDefinePtr *attrs; /* the array of attributes definitions */
+};
+
+#define IS_DETERMINIST 1
+#define IS_NEEDCHECK 2
+
+/**
+ * xmlRelaxNGPartitions:
+ *
+ * A RelaxNGs partition associated to an interleave group
+ */
+typedef struct _xmlRelaxNGPartition xmlRelaxNGPartition;
+typedef xmlRelaxNGPartition *xmlRelaxNGPartitionPtr;
+struct _xmlRelaxNGPartition {
+ int nbgroups; /* number of groups in the partitions */
+ xmlHashTablePtr triage; /* hash table used to direct nodes to the
+ * right group when possible */
+ int flags; /* determinist ? */
+ xmlRelaxNGInterleaveGroupPtr *groups;
+};
+
+/**
+ * xmlRelaxNGValidState:
+ *
+ * A RelaxNGs validation state
+ */
+#define MAX_ATTR 20
+typedef struct _xmlRelaxNGValidState xmlRelaxNGValidState;
+typedef xmlRelaxNGValidState *xmlRelaxNGValidStatePtr;
+struct _xmlRelaxNGValidState {
+ xmlNodePtr node; /* the current node */
+ xmlNodePtr seq; /* the sequence of children left to validate */
+ int nbAttrs; /* the number of attributes */
+ int maxAttrs; /* the size of attrs */
+ int nbAttrLeft; /* the number of attributes left to validate */
+ xmlChar *value; /* the value when operating on string */
+ xmlChar *endvalue; /* the end value when operating on string */
+ xmlAttrPtr *attrs; /* the array of attributes */
+};
+
+/**
+ * xmlRelaxNGStates:
+ *
+ * A RelaxNGs container for validation state
+ */
+typedef struct _xmlRelaxNGStates xmlRelaxNGStates;
+typedef xmlRelaxNGStates *xmlRelaxNGStatesPtr;
+struct _xmlRelaxNGStates {
+ int nbState; /* the number of states */
+ int maxState; /* the size of the array */
+ xmlRelaxNGValidStatePtr *tabState;
+};
+
+#define ERROR_IS_DUP 1
+
+/**
+ * xmlRelaxNGValidError:
+ *
+ * A RelaxNGs validation error
+ */
+typedef struct _xmlRelaxNGValidError xmlRelaxNGValidError;
+typedef xmlRelaxNGValidError *xmlRelaxNGValidErrorPtr;
+struct _xmlRelaxNGValidError {
+ xmlRelaxNGValidErr err; /* the error number */
+ int flags; /* flags */
+ xmlNodePtr node; /* the current node */
+ xmlNodePtr seq; /* the current child */
+ const xmlChar *arg1; /* first arg */
+ const xmlChar *arg2; /* second arg */
+};
+
+/**
+ * xmlRelaxNGValidCtxt:
+ *
+ * A RelaxNGs validation context
+ */
+
+struct _xmlRelaxNGValidCtxt {
+ void *userData; /* user specific data block */
+ xmlRelaxNGValidityErrorFunc error; /* the callback in case of errors */
+ xmlRelaxNGValidityWarningFunc warning; /* the callback in case of warning */
+ xmlStructuredErrorFunc serror;
+ int nbErrors; /* number of errors in validation */
+
+ xmlRelaxNGPtr schema; /* The schema in use */
+ xmlDocPtr doc; /* the document being validated */
+ int flags; /* validation flags */
+ int depth; /* validation depth */
+ int idref; /* requires idref checking */
+ int errNo; /* the first error found */
+
+ /*
+ * Errors accumulated in branches may have to be stacked to be
+ * provided back when it's sure they affect validation.
+ */
+ xmlRelaxNGValidErrorPtr err; /* Last error */
+ int errNr; /* Depth of the error stack */
+ int errMax; /* Max depth of the error stack */
+ xmlRelaxNGValidErrorPtr errTab; /* stack of errors */
+
+ xmlRelaxNGValidStatePtr state; /* the current validation state */
+ xmlRelaxNGStatesPtr states; /* the accumulated state list */
+
+ xmlRelaxNGStatesPtr freeState; /* the pool of free valid states */
+ int freeStatesNr;
+ int freeStatesMax;
+ xmlRelaxNGStatesPtr *freeStates; /* the pool of free state groups */
+
+ /*
+ * This is used for "progressive" validation
+ */
+ xmlRegExecCtxtPtr elem; /* the current element regexp */
+ int elemNr; /* the number of element validated */
+ int elemMax; /* the max depth of elements */
+ xmlRegExecCtxtPtr *elemTab; /* the stack of regexp runtime */
+ int pstate; /* progressive state */
+ xmlNodePtr pnode; /* the current node */
+ xmlRelaxNGDefinePtr pdef; /* the non-streamable definition */
+ int perr; /* signal error in content model
+ * outside the regexp */
+};
+
+/**
+ * xmlRelaxNGInclude:
+ *
+ * Structure associated to a RelaxNGs document element
+ */
+struct _xmlRelaxNGInclude {
+ xmlRelaxNGIncludePtr next; /* keep a chain of includes */
+ xmlChar *href; /* the normalized href value */
+ xmlDocPtr doc; /* the associated XML document */
+ xmlRelaxNGDefinePtr content; /* the definitions */
+ xmlRelaxNGPtr schema; /* the schema */
+};
+
+/**
+ * xmlRelaxNGDocument:
+ *
+ * Structure associated to a RelaxNGs document element
+ */
+struct _xmlRelaxNGDocument {
+ xmlRelaxNGDocumentPtr next; /* keep a chain of documents */
+ xmlChar *href; /* the normalized href value */
+ xmlDocPtr doc; /* the associated XML document */
+ xmlRelaxNGDefinePtr content; /* the definitions */
+ xmlRelaxNGPtr schema; /* the schema */
+};
+
+
+/************************************************************************
+ * *
+ * Some factorized error routines *
+ * *
+ ************************************************************************/
+
+/**
+ * xmlRngPErrMemory:
+ * @ctxt: an Relax-NG parser context
+ * @extra: extra informations
+ *
+ * Handle a redefinition of attribute error
+ */
+static void
+xmlRngPErrMemory(xmlRelaxNGParserCtxtPtr ctxt, const char *extra)
+{
+ xmlStructuredErrorFunc schannel = NULL;
+ xmlGenericErrorFunc channel = NULL;
+ void *data = NULL;
+
+ if (ctxt != NULL) {
+ if (ctxt->serror != NULL)
+ schannel = ctxt->serror;
+ else
+ channel = ctxt->error;
+ data = ctxt->userData;
+ ctxt->nbErrors++;
+ }
+ if (extra)
+ __xmlRaiseError(schannel, channel, data,
+ NULL, NULL, XML_FROM_RELAXNGP,
+ XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
+ NULL, NULL, 0, 0,
+ "Memory allocation failed : %s\n", extra);
+ else
+ __xmlRaiseError(schannel, channel, data,
+ NULL, NULL, XML_FROM_RELAXNGP,
+ XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL,
+ NULL, NULL, 0, 0, "Memory allocation failed\n");
+}
+
+/**
+ * xmlRngVErrMemory:
+ * @ctxt: a Relax-NG validation context
+ * @extra: extra informations
+ *
+ * Handle a redefinition of attribute error
+ */
+static void
+xmlRngVErrMemory(xmlRelaxNGValidCtxtPtr ctxt, const char *extra)
+{
+ xmlStructuredErrorFunc schannel = NULL;
+ xmlGenericErrorFunc channel = NULL;
+ void *data = NULL;
+
+ if (ctxt != NULL) {
+ if (ctxt->serror != NULL)
+ schannel = ctxt->serror;
+ else
+ channel = ctxt->error;
+ data = ctxt->userData;
+ ctxt->nbErrors++;
+ }
+ if (extra)
+ __xmlRaiseError(schannel, channel, data,
+ NULL, NULL, XML_FROM_RELAXNGV,
+ XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
+ NULL, NULL, 0, 0,
+ "Memory allocation failed : %s\n", extra);
+ else
+ __xmlRaiseError(schannel, channel, data,
+ NULL, NULL, XML_FROM_RELAXNGV,
+ XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, NULL,
+ NULL, NULL, 0, 0, "Memory allocation failed\n");
+}
+
+/**
+ * xmlRngPErr:
+ * @ctxt: a Relax-NG parser context
+ * @node: the node raising the error
+ * @error: the error code
+ * @msg: message
+ * @str1: extra info
+ * @str2: extra info
+ *
+ * Handle a Relax NG Parsing error
+ */
+static void
+xmlRngPErr(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node, int error,
+ const char *msg, const xmlChar * str1, const xmlChar * str2)
+{
+ xmlStructuredErrorFunc schannel = NULL;
+ xmlGenericErrorFunc channel = NULL;
+ void *data = NULL;
+
+ if (ctxt != NULL) {
+ if (ctxt->serror != NULL)
+ schannel = ctxt->serror;
+ else
+ channel = ctxt->error;
+ data = ctxt->userData;
+ ctxt->nbErrors++;
+ }
+ __xmlRaiseError(schannel, channel, data,
+ NULL, node, XML_FROM_RELAXNGP,
+ error, XML_ERR_ERROR, NULL, 0,
+ (const char *) str1, (const char *) str2, NULL, 0, 0,
+ msg, str1, str2);
+}
+
+/**
+ * xmlRngVErr:
+ * @ctxt: a Relax-NG validation context
+ * @node: the node raising the error
+ * @error: the error code
+ * @msg: message
+ * @str1: extra info
+ * @str2: extra info
+ *
+ * Handle a Relax NG Validation error
+ */
+static void
+xmlRngVErr(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node, int error,
+ const char *msg, const xmlChar * str1, const xmlChar * str2)
+{
+ xmlStructuredErrorFunc schannel = NULL;
+ xmlGenericErrorFunc channel = NULL;
+ void *data = NULL;
+
+ if (ctxt != NULL) {
+ if (ctxt->serror != NULL)
+ schannel = ctxt->serror;
+ else
+ channel = ctxt->error;
+ data = ctxt->userData;
+ ctxt->nbErrors++;
+ }
+ __xmlRaiseError(schannel, channel, data,
+ NULL, node, XML_FROM_RELAXNGV,
+ error, XML_ERR_ERROR, NULL, 0,
+ (const char *) str1, (const char *) str2, NULL, 0, 0,
+ msg, str1, str2);
+}
+
+/************************************************************************
+ * *
+ * Preliminary type checking interfaces *
+ * *
+ ************************************************************************/
+
+/**
+ * xmlRelaxNGTypeHave:
+ * @data: data needed for the library
+ * @type: the type name
+ * @value: the value to check
+ *
+ * Function provided by a type library to check if a type is exported
+ *
+ * Returns 1 if yes, 0 if no and -1 in case of error.
+ */
+typedef int (*xmlRelaxNGTypeHave) (void *data, const xmlChar * type);
+
+/**
+ * xmlRelaxNGTypeCheck:
+ * @data: data needed for the library
+ * @type: the type name
+ * @value: the value to check
+ * @result: place to store the result if needed
+ *
+ * Function provided by a type library to check if a value match a type
+ *
+ * Returns 1 if yes, 0 if no and -1 in case of error.
+ */
+typedef int (*xmlRelaxNGTypeCheck) (void *data, const xmlChar * type,
+ const xmlChar * value, void **result,
+ xmlNodePtr node);
+
+/**
+ * xmlRelaxNGFacetCheck:
+ * @data: data needed for the library
+ * @type: the type name
+ * @facet: the facet name
+ * @val: the facet value
+ * @strval: the string value
+ * @value: the value to check
+ *
+ * Function provided by a type library to check a value facet
+ *
+ * Returns 1 if yes, 0 if no and -1 in case of error.
+ */
+typedef int (*xmlRelaxNGFacetCheck) (void *data, const xmlChar * type,
+ const xmlChar * facet,
+ const xmlChar * val,
+ const xmlChar * strval, void *value);
+
+/**
+ * xmlRelaxNGTypeFree:
+ * @data: data needed for the library
+ * @result: the value to free
+ *
+ * Function provided by a type library to free a returned result
+ */
+typedef void (*xmlRelaxNGTypeFree) (void *data, void *result);
+
+/**
+ * xmlRelaxNGTypeCompare:
+ * @data: data needed for the library
+ * @type: the type name
+ * @value1: the first value
+ * @value2: the second value
+ *
+ * Function provided by a type library to compare two values accordingly
+ * to a type.
+ *
+ * Returns 1 if yes, 0 if no and -1 in case of error.
+ */
+typedef int (*xmlRelaxNGTypeCompare) (void *data, const xmlChar * type,
+ const xmlChar * value1,
+ xmlNodePtr ctxt1,
+ void *comp1,
+ const xmlChar * value2,
+ xmlNodePtr ctxt2);
+typedef struct _xmlRelaxNGTypeLibrary xmlRelaxNGTypeLibrary;
+typedef xmlRelaxNGTypeLibrary *xmlRelaxNGTypeLibraryPtr;
+struct _xmlRelaxNGTypeLibrary {
+ const xmlChar *namespace; /* the datatypeLibrary value */
+ void *data; /* data needed for the library */
+ xmlRelaxNGTypeHave have; /* the export function */
+ xmlRelaxNGTypeCheck check; /* the checking function */
+ xmlRelaxNGTypeCompare comp; /* the compare function */
+ xmlRelaxNGFacetCheck facet; /* the facet check function */
+ xmlRelaxNGTypeFree freef; /* the freeing function */
+};
+
+/************************************************************************
+ * *
+ * Allocation functions *
+ * *
+ ************************************************************************/
+static void xmlRelaxNGFreeGrammar(xmlRelaxNGGrammarPtr grammar);
+static void xmlRelaxNGFreeDefine(xmlRelaxNGDefinePtr define);
+static void xmlRelaxNGNormExtSpace(xmlChar * value);
+static void xmlRelaxNGFreeInnerSchema(xmlRelaxNGPtr schema);
+static int xmlRelaxNGEqualValidState(xmlRelaxNGValidCtxtPtr ctxt
+ ATTRIBUTE_UNUSED,
+ xmlRelaxNGValidStatePtr state1,
+ xmlRelaxNGValidStatePtr state2);
+static void xmlRelaxNGFreeValidState(xmlRelaxNGValidCtxtPtr ctxt,
+ xmlRelaxNGValidStatePtr state);
+
+/**
+ * xmlRelaxNGFreeDocument:
+ * @docu: a document structure
+ *
+ * Deallocate a RelaxNG document structure.
+ */
+static void
+xmlRelaxNGFreeDocument(xmlRelaxNGDocumentPtr docu)
+{
+ if (docu == NULL)
+ return;
+
+ if (docu->href != NULL)
+ xmlFree(docu->href);
+ if (docu->doc != NULL)
+ xmlFreeDoc(docu->doc);
+ if (docu->schema != NULL)
+ xmlRelaxNGFreeInnerSchema(docu->schema);
+ xmlFree(docu);
+}
+
+/**
+ * xmlRelaxNGFreeDocumentList:
+ * @docu: a list of document structure
+ *
+ * Deallocate a RelaxNG document structures.
+ */
+static void
+xmlRelaxNGFreeDocumentList(xmlRelaxNGDocumentPtr docu)
+{
+ xmlRelaxNGDocumentPtr next;
+
+ while (docu != NULL) {
+ next = docu->next;
+ xmlRelaxNGFreeDocument(docu);
+ docu = next;
+ }
+}
+
+/**
+ * xmlRelaxNGFreeInclude:
+ * @incl: a include structure
+ *
+ * Deallocate a RelaxNG include structure.
+ */
+static void
+xmlRelaxNGFreeInclude(xmlRelaxNGIncludePtr incl)
+{
+ if (incl == NULL)
+ return;
+
+ if (incl->href != NULL)
+ xmlFree(incl->href);
+ if (incl->doc != NULL)
+ xmlFreeDoc(incl->doc);
+ if (incl->schema != NULL)
+ xmlRelaxNGFree(incl->schema);
+ xmlFree(incl);
+}
+
+/**
+ * xmlRelaxNGFreeIncludeList:
+ * @incl: a include structure list
+ *
+ * Deallocate a RelaxNG include structure.
+ */
+static void
+xmlRelaxNGFreeIncludeList(xmlRelaxNGIncludePtr incl)
+{
+ xmlRelaxNGIncludePtr next;
+
+ while (incl != NULL) {
+ next = incl->next;
+ xmlRelaxNGFreeInclude(incl);
+ incl = next;
+ }
+}
+
+/**
+ * xmlRelaxNGNewRelaxNG:
+ * @ctxt: a Relax-NG validation context (optional)
+ *
+ * Allocate a new RelaxNG structure.
+ *
+ * Returns the newly allocated structure or NULL in case or error
+ */
+static xmlRelaxNGPtr
+xmlRelaxNGNewRelaxNG(xmlRelaxNGParserCtxtPtr ctxt)
+{
+ xmlRelaxNGPtr ret;
+
+ ret = (xmlRelaxNGPtr) xmlMalloc(sizeof(xmlRelaxNG));
+ if (ret == NULL) {
+ xmlRngPErrMemory(ctxt, NULL);
+ return (NULL);
+ }
+ memset(ret, 0, sizeof(xmlRelaxNG));
+
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGFreeInnerSchema:
+ * @schema: a schema structure
+ *
+ * Deallocate a RelaxNG schema structure.
+ */
+static void
+xmlRelaxNGFreeInnerSchema(xmlRelaxNGPtr schema)
+{
+ if (schema == NULL)
+ return;
+
+ if (schema->doc != NULL)
+ xmlFreeDoc(schema->doc);
+ if (schema->defTab != NULL) {
+ int i;
+
+ for (i = 0; i < schema->defNr; i++)
+ xmlRelaxNGFreeDefine(schema->defTab[i]);
+ xmlFree(schema->defTab);
+ }
+
+ xmlFree(schema);
+}
+
+/**
+ * xmlRelaxNGFree:
+ * @schema: a schema structure
+ *
+ * Deallocate a RelaxNG structure.
+ */
+void
+xmlRelaxNGFree(xmlRelaxNGPtr schema)
+{
+ if (schema == NULL)
+ return;
+
+ if (schema->topgrammar != NULL)
+ xmlRelaxNGFreeGrammar(schema->topgrammar);
+ if (schema->doc != NULL)
+ xmlFreeDoc(schema->doc);
+ if (schema->documents != NULL)
+ xmlRelaxNGFreeDocumentList(schema->documents);
+ if (schema->includes != NULL)
+ xmlRelaxNGFreeIncludeList(schema->includes);
+ if (schema->defTab != NULL) {
+ int i;
+
+ for (i = 0; i < schema->defNr; i++)
+ xmlRelaxNGFreeDefine(schema->defTab[i]);
+ xmlFree(schema->defTab);
+ }
+
+ xmlFree(schema);
+}
+
+/**
+ * xmlRelaxNGNewGrammar:
+ * @ctxt: a Relax-NG validation context (optional)
+ *
+ * Allocate a new RelaxNG grammar.
+ *
+ * Returns the newly allocated structure or NULL in case or error
+ */
+static xmlRelaxNGGrammarPtr
+xmlRelaxNGNewGrammar(xmlRelaxNGParserCtxtPtr ctxt)
+{
+ xmlRelaxNGGrammarPtr ret;
+
+ ret = (xmlRelaxNGGrammarPtr) xmlMalloc(sizeof(xmlRelaxNGGrammar));
+ if (ret == NULL) {
+ xmlRngPErrMemory(ctxt, NULL);
+ return (NULL);
+ }
+ memset(ret, 0, sizeof(xmlRelaxNGGrammar));
+
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGFreeGrammar:
+ * @grammar: a grammar structure
+ *
+ * Deallocate a RelaxNG grammar structure.
+ */
+static void
+xmlRelaxNGFreeGrammar(xmlRelaxNGGrammarPtr grammar)
+{
+ if (grammar == NULL)
+ return;
+
+ if (grammar->children != NULL) {
+ xmlRelaxNGFreeGrammar(grammar->children);
+ }
+ if (grammar->next != NULL) {
+ xmlRelaxNGFreeGrammar(grammar->next);
+ }
+ if (grammar->refs != NULL) {
+ xmlHashFree(grammar->refs, NULL);
+ }
+ if (grammar->defs != NULL) {
+ xmlHashFree(grammar->defs, NULL);
+ }
+
+ xmlFree(grammar);
+}
+
+/**
+ * xmlRelaxNGNewDefine:
+ * @ctxt: a Relax-NG validation context
+ * @node: the node in the input document.
+ *
+ * Allocate a new RelaxNG define.
+ *
+ * Returns the newly allocated structure or NULL in case or error
+ */
+static xmlRelaxNGDefinePtr
+xmlRelaxNGNewDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
+{
+ xmlRelaxNGDefinePtr ret;
+
+ if (ctxt->defMax == 0) {
+ ctxt->defMax = 16;
+ ctxt->defNr = 0;
+ ctxt->defTab = (xmlRelaxNGDefinePtr *)
+ xmlMalloc(ctxt->defMax * sizeof(xmlRelaxNGDefinePtr));
+ if (ctxt->defTab == NULL) {
+ xmlRngPErrMemory(ctxt, "allocating define\n");
+ return (NULL);
+ }
+ } else if (ctxt->defMax <= ctxt->defNr) {
+ xmlRelaxNGDefinePtr *tmp;
+
+ ctxt->defMax *= 2;
+ tmp = (xmlRelaxNGDefinePtr *) xmlRealloc(ctxt->defTab,
+ ctxt->defMax *
+ sizeof
+ (xmlRelaxNGDefinePtr));
+ if (tmp == NULL) {
+ xmlRngPErrMemory(ctxt, "allocating define\n");
+ return (NULL);
+ }
+ ctxt->defTab = tmp;
+ }
+ ret = (xmlRelaxNGDefinePtr) xmlMalloc(sizeof(xmlRelaxNGDefine));
+ if (ret == NULL) {
+ xmlRngPErrMemory(ctxt, "allocating define\n");
+ return (NULL);
+ }
+ memset(ret, 0, sizeof(xmlRelaxNGDefine));
+ ctxt->defTab[ctxt->defNr++] = ret;
+ ret->node = node;
+ ret->depth = -1;
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGFreePartition:
+ * @partitions: a partition set structure
+ *
+ * Deallocate RelaxNG partition set structures.
+ */
+static void
+xmlRelaxNGFreePartition(xmlRelaxNGPartitionPtr partitions)
+{
+ xmlRelaxNGInterleaveGroupPtr group;
+ int j;
+
+ if (partitions != NULL) {
+ if (partitions->groups != NULL) {
+ for (j = 0; j < partitions->nbgroups; j++) {
+ group = partitions->groups[j];
+ if (group != NULL) {
+ if (group->defs != NULL)
+ xmlFree(group->defs);
+ if (group->attrs != NULL)
+ xmlFree(group->attrs);
+ xmlFree(group);
+ }
+ }
+ xmlFree(partitions->groups);
+ }
+ if (partitions->triage != NULL) {
+ xmlHashFree(partitions->triage, NULL);
+ }
+ xmlFree(partitions);
+ }
+}
+
+/**
+ * xmlRelaxNGFreeDefine:
+ * @define: a define structure
+ *
+ * Deallocate a RelaxNG define structure.
+ */
+static void
+xmlRelaxNGFreeDefine(xmlRelaxNGDefinePtr define)
+{
+ if (define == NULL)
+ return;
+
+ if ((define->type == XML_RELAXNG_VALUE) && (define->attrs != NULL)) {
+ xmlRelaxNGTypeLibraryPtr lib;
+
+ lib = (xmlRelaxNGTypeLibraryPtr) define->data;
+ if ((lib != NULL) && (lib->freef != NULL))
+ lib->freef(lib->data, (void *) define->attrs);
+ }
+ if ((define->data != NULL) && (define->type == XML_RELAXNG_INTERLEAVE))
+ xmlRelaxNGFreePartition((xmlRelaxNGPartitionPtr) define->data);
+ if ((define->data != NULL) && (define->type == XML_RELAXNG_CHOICE))
+ xmlHashFree((xmlHashTablePtr) define->data, NULL);
+ if (define->name != NULL)
+ xmlFree(define->name);
+ if (define->ns != NULL)
+ xmlFree(define->ns);
+ if (define->value != NULL)
+ xmlFree(define->value);
+ if (define->contModel != NULL)
+ xmlRegFreeRegexp(define->contModel);
+ xmlFree(define);
+}
+
+/**
+ * xmlRelaxNGNewStates:
+ * @ctxt: a Relax-NG validation context
+ * @size: the default size for the container
+ *
+ * Allocate a new RelaxNG validation state container
+ *
+ * Returns the newly allocated structure or NULL in case or error
+ */
+static xmlRelaxNGStatesPtr
+xmlRelaxNGNewStates(xmlRelaxNGValidCtxtPtr ctxt, int size)
+{
+ xmlRelaxNGStatesPtr ret;
+
+ if ((ctxt != NULL) &&
+ (ctxt->freeState != NULL) && (ctxt->freeStatesNr > 0)) {
+ ctxt->freeStatesNr--;
+ ret = ctxt->freeStates[ctxt->freeStatesNr];
+ ret->nbState = 0;
+ return (ret);
+ }
+ if (size < 16)
+ size = 16;
+
+ ret = (xmlRelaxNGStatesPtr) xmlMalloc(sizeof(xmlRelaxNGStates) +
+ (size -
+ 1) *
+ sizeof(xmlRelaxNGValidStatePtr));
+ if (ret == NULL) {
+ xmlRngVErrMemory(ctxt, "allocating states\n");
+ return (NULL);
+ }
+ ret->nbState = 0;
+ ret->maxState = size;
+ ret->tabState = (xmlRelaxNGValidStatePtr *) xmlMalloc((size) *
+ sizeof
+ (xmlRelaxNGValidStatePtr));
+ if (ret->tabState == NULL) {
+ xmlRngVErrMemory(ctxt, "allocating states\n");
+ xmlFree(ret);
+ return (NULL);
+ }
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGAddStateUniq:
+ * @ctxt: a Relax-NG validation context
+ * @states: the states container
+ * @state: the validation state
+ *
+ * Add a RelaxNG validation state to the container without checking
+ * for unicity.
+ *
+ * Return 1 in case of success and 0 if this is a duplicate and -1 on error
+ */
+static int
+xmlRelaxNGAddStatesUniq(xmlRelaxNGValidCtxtPtr ctxt,
+ xmlRelaxNGStatesPtr states,
+ xmlRelaxNGValidStatePtr state)
+{
+ if (state == NULL) {
+ return (-1);
+ }
+ if (states->nbState >= states->maxState) {
+ xmlRelaxNGValidStatePtr *tmp;
+ int size;
+
+ size = states->maxState * 2;
+ tmp = (xmlRelaxNGValidStatePtr *) xmlRealloc(states->tabState,
+ (size) *
+ sizeof
+ (xmlRelaxNGValidStatePtr));
+ if (tmp == NULL) {
+ xmlRngVErrMemory(ctxt, "adding states\n");
+ return (-1);
+ }
+ states->tabState = tmp;
+ states->maxState = size;
+ }
+ states->tabState[states->nbState++] = state;
+ return (1);
+}
+
+/**
+ * xmlRelaxNGAddState:
+ * @ctxt: a Relax-NG validation context
+ * @states: the states container
+ * @state: the validation state
+ *
+ * Add a RelaxNG validation state to the container
+ *
+ * Return 1 in case of success and 0 if this is a duplicate and -1 on error
+ */
+static int
+xmlRelaxNGAddStates(xmlRelaxNGValidCtxtPtr ctxt,
+ xmlRelaxNGStatesPtr states,
+ xmlRelaxNGValidStatePtr state)
+{
+ int i;
+
+ if (state == NULL) {
+ return (-1);
+ }
+ if (states->nbState >= states->maxState) {
+ xmlRelaxNGValidStatePtr *tmp;
+ int size;
+
+ size = states->maxState * 2;
+ tmp = (xmlRelaxNGValidStatePtr *) xmlRealloc(states->tabState,
+ (size) *
+ sizeof
+ (xmlRelaxNGValidStatePtr));
+ if (tmp == NULL) {
+ xmlRngVErrMemory(ctxt, "adding states\n");
+ return (-1);
+ }
+ states->tabState = tmp;
+ states->maxState = size;
+ }
+ for (i = 0; i < states->nbState; i++) {
+ if (xmlRelaxNGEqualValidState(ctxt, state, states->tabState[i])) {
+ xmlRelaxNGFreeValidState(ctxt, state);
+ return (0);
+ }
+ }
+ states->tabState[states->nbState++] = state;
+ return (1);
+}
+
+/**
+ * xmlRelaxNGFreeStates:
+ * @ctxt: a Relax-NG validation context
+ * @states: teh container
+ *
+ * Free a RelaxNG validation state container
+ */
+static void
+xmlRelaxNGFreeStates(xmlRelaxNGValidCtxtPtr ctxt,
+ xmlRelaxNGStatesPtr states)
+{
+ if (states == NULL)
+ return;
+ if ((ctxt != NULL) && (ctxt->freeStates == NULL)) {
+ ctxt->freeStatesMax = 40;
+ ctxt->freeStatesNr = 0;
+ ctxt->freeStates = (xmlRelaxNGStatesPtr *)
+ xmlMalloc(ctxt->freeStatesMax * sizeof(xmlRelaxNGStatesPtr));
+ if (ctxt->freeStates == NULL) {
+ xmlRngVErrMemory(ctxt, "storing states\n");
+ }
+ } else if ((ctxt != NULL)
+ && (ctxt->freeStatesNr >= ctxt->freeStatesMax)) {
+ xmlRelaxNGStatesPtr *tmp;
+
+ tmp = (xmlRelaxNGStatesPtr *) xmlRealloc(ctxt->freeStates,
+ 2 * ctxt->freeStatesMax *
+ sizeof
+ (xmlRelaxNGStatesPtr));
+ if (tmp == NULL) {
+ xmlRngVErrMemory(ctxt, "storing states\n");
+ xmlFree(states->tabState);
+ xmlFree(states);
+ return;
+ }
+ ctxt->freeStates = tmp;
+ ctxt->freeStatesMax *= 2;
+ }
+ if ((ctxt == NULL) || (ctxt->freeStates == NULL)) {
+ xmlFree(states->tabState);
+ xmlFree(states);
+ } else {
+ ctxt->freeStates[ctxt->freeStatesNr++] = states;
+ }
+}
+
+/**
+ * xmlRelaxNGNewValidState:
+ * @ctxt: a Relax-NG validation context
+ * @node: the current node or NULL for the document
+ *
+ * Allocate a new RelaxNG validation state
+ *
+ * Returns the newly allocated structure or NULL in case or error
+ */
+static xmlRelaxNGValidStatePtr
+xmlRelaxNGNewValidState(xmlRelaxNGValidCtxtPtr ctxt, xmlNodePtr node)
+{
+ xmlRelaxNGValidStatePtr ret;
+ xmlAttrPtr attr;
+ xmlAttrPtr attrs[MAX_ATTR];
+ int nbAttrs = 0;
+ xmlNodePtr root = NULL;
+
+ if (node == NULL) {
+ root = xmlDocGetRootElement(ctxt->doc);
+ if (root == NULL)
+ return (NULL);
+ } else {
+ attr = node->properties;
+ while (attr != NULL) {
+ if (nbAttrs < MAX_ATTR)
+ attrs[nbAttrs++] = attr;
+ else
+ nbAttrs++;
+ attr = attr->next;
+ }
+ }
+ if ((ctxt->freeState != NULL) && (ctxt->freeState->nbState > 0)) {
+ ctxt->freeState->nbState--;
+ ret = ctxt->freeState->tabState[ctxt->freeState->nbState];
+ } else {
+ ret =
+ (xmlRelaxNGValidStatePtr)
+ xmlMalloc(sizeof(xmlRelaxNGValidState));
+ if (ret == NULL) {
+ xmlRngVErrMemory(ctxt, "allocating states\n");
+ return (NULL);
+ }
+ memset(ret, 0, sizeof(xmlRelaxNGValidState));
+ }
+ ret->value = NULL;
+ ret->endvalue = NULL;
+ if (node == NULL) {
+ ret->node = (xmlNodePtr) ctxt->doc;
+ ret->seq = root;
+ } else {
+ ret->node = node;
+ ret->seq = node->children;
+ }
+ ret->nbAttrs = 0;
+ if (nbAttrs > 0) {
+ if (ret->attrs == NULL) {
+ if (nbAttrs < 4)
+ ret->maxAttrs = 4;
+ else
+ ret->maxAttrs = nbAttrs;
+ ret->attrs = (xmlAttrPtr *) xmlMalloc(ret->maxAttrs *
+ sizeof(xmlAttrPtr));
+ if (ret->attrs == NULL) {
+ xmlRngVErrMemory(ctxt, "allocating states\n");
+ return (ret);
+ }
+ } else if (ret->maxAttrs < nbAttrs) {
+ xmlAttrPtr *tmp;
+
+ tmp = (xmlAttrPtr *) xmlRealloc(ret->attrs, nbAttrs *
+ sizeof(xmlAttrPtr));
+ if (tmp == NULL) {
+ xmlRngVErrMemory(ctxt, "allocating states\n");
+ return (ret);
+ }
+ ret->attrs = tmp;
+ ret->maxAttrs = nbAttrs;
+ }
+ ret->nbAttrs = nbAttrs;
+ if (nbAttrs < MAX_ATTR) {
+ memcpy(ret->attrs, attrs, sizeof(xmlAttrPtr) * nbAttrs);
+ } else {
+ attr = node->properties;
+ nbAttrs = 0;
+ while (attr != NULL) {
+ ret->attrs[nbAttrs++] = attr;
+ attr = attr->next;
+ }
+ }
+ }
+ ret->nbAttrLeft = ret->nbAttrs;
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGCopyValidState:
+ * @ctxt: a Relax-NG validation context
+ * @state: a validation state
+ *
+ * Copy the validation state
+ *
+ * Returns the newly allocated structure or NULL in case or error
+ */
+static xmlRelaxNGValidStatePtr
+xmlRelaxNGCopyValidState(xmlRelaxNGValidCtxtPtr ctxt,
+ xmlRelaxNGValidStatePtr state)
+{
+ xmlRelaxNGValidStatePtr ret;
+ unsigned int maxAttrs;
+ xmlAttrPtr *attrs;
+
+ if (state == NULL)
+ return (NULL);
+ if ((ctxt->freeState != NULL) && (ctxt->freeState->nbState > 0)) {
+ ctxt->freeState->nbState--;
+ ret = ctxt->freeState->tabState[ctxt->freeState->nbState];
+ } else {
+ ret =
+ (xmlRelaxNGValidStatePtr)
+ xmlMalloc(sizeof(xmlRelaxNGValidState));
+ if (ret == NULL) {
+ xmlRngVErrMemory(ctxt, "allocating states\n");
+ return (NULL);
+ }
+ memset(ret, 0, sizeof(xmlRelaxNGValidState));
+ }
+ attrs = ret->attrs;
+ maxAttrs = ret->maxAttrs;
+ memcpy(ret, state, sizeof(xmlRelaxNGValidState));
+ ret->attrs = attrs;
+ ret->maxAttrs = maxAttrs;
+ if (state->nbAttrs > 0) {
+ if (ret->attrs == NULL) {
+ ret->maxAttrs = state->maxAttrs;
+ ret->attrs = (xmlAttrPtr *) xmlMalloc(ret->maxAttrs *
+ sizeof(xmlAttrPtr));
+ if (ret->attrs == NULL) {
+ xmlRngVErrMemory(ctxt, "allocating states\n");
+ ret->nbAttrs = 0;
+ return (ret);
+ }
+ } else if (ret->maxAttrs < state->nbAttrs) {
+ xmlAttrPtr *tmp;
+
+ tmp = (xmlAttrPtr *) xmlRealloc(ret->attrs, state->maxAttrs *
+ sizeof(xmlAttrPtr));
+ if (tmp == NULL) {
+ xmlRngVErrMemory(ctxt, "allocating states\n");
+ ret->nbAttrs = 0;
+ return (ret);
+ }
+ ret->maxAttrs = state->maxAttrs;
+ ret->attrs = tmp;
+ }
+ memcpy(ret->attrs, state->attrs,
+ state->nbAttrs * sizeof(xmlAttrPtr));
+ }
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGEqualValidState:
+ * @ctxt: a Relax-NG validation context
+ * @state1: a validation state
+ * @state2: a validation state
+ *
+ * Compare the validation states for equality
+ *
+ * Returns 1 if equald, 0 otherwise
+ */
+static int
+xmlRelaxNGEqualValidState(xmlRelaxNGValidCtxtPtr ctxt ATTRIBUTE_UNUSED,
+ xmlRelaxNGValidStatePtr state1,
+ xmlRelaxNGValidStatePtr state2)
+{
+ int i;
+
+ if ((state1 == NULL) || (state2 == NULL))
+ return (0);
+ if (state1 == state2)
+ return (1);
+ if (state1->node != state2->node)
+ return (0);
+ if (state1->seq != state2->seq)
+ return (0);
+ if (state1->nbAttrLeft != state2->nbAttrLeft)
+ return (0);
+ if (state1->nbAttrs != state2->nbAttrs)
+ return (0);
+ if (state1->endvalue != state2->endvalue)
+ return (0);
+ if ((state1->value != state2->value) &&
+ (!xmlStrEqual(state1->value, state2->value)))
+ return (0);
+ for (i = 0; i < state1->nbAttrs; i++) {
+ if (state1->attrs[i] != state2->attrs[i])
+ return (0);
+ }
+ return (1);
+}
+
+/**
+ * xmlRelaxNGFreeValidState:
+ * @state: a validation state structure
+ *
+ * Deallocate a RelaxNG validation state structure.
+ */
+static void
+xmlRelaxNGFreeValidState(xmlRelaxNGValidCtxtPtr ctxt,
+ xmlRelaxNGValidStatePtr state)
+{
+ if (state == NULL)
+ return;
+
+ if ((ctxt != NULL) && (ctxt->freeState == NULL)) {
+ ctxt->freeState = xmlRelaxNGNewStates(ctxt, 40);
+ }
+ if ((ctxt == NULL) || (ctxt->freeState == NULL)) {
+ if (state->attrs != NULL)
+ xmlFree(state->attrs);
+ xmlFree(state);
+ } else {
+ xmlRelaxNGAddStatesUniq(ctxt, ctxt->freeState, state);
+ }
+}
+
+/************************************************************************
+ * *
+ * Semi internal functions *
+ * *
+ ************************************************************************/
+
+/**
+ * xmlRelaxParserSetFlag:
+ * @ctxt: a RelaxNG parser context
+ * @flags: a set of flags values
+ *
+ * Semi private function used to pass informations to a parser context
+ * which are a combination of xmlRelaxNGParserFlag .
+ *
+ * Returns 0 if success and -1 in case of error
+ */
+int
+xmlRelaxParserSetFlag(xmlRelaxNGParserCtxtPtr ctxt, int flags)
+{
+ if (ctxt == NULL) return(-1);
+ if (flags & XML_RELAXNGP_FREE_DOC) {
+ ctxt->crng |= XML_RELAXNGP_FREE_DOC;
+ flags -= XML_RELAXNGP_FREE_DOC;
+ }
+ if (flags & XML_RELAXNGP_CRNG) {
+ ctxt->crng |= XML_RELAXNGP_CRNG;
+ flags -= XML_RELAXNGP_CRNG;
+ }
+ if (flags != 0) return(-1);
+ return(0);
+}
+
+/************************************************************************
+ * *
+ * Document functions *
+ * *
+ ************************************************************************/
+static xmlDocPtr xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt,
+ xmlDocPtr doc);
+
+/**
+ * xmlRelaxNGIncludePush:
+ * @ctxt: the parser context
+ * @value: the element doc
+ *
+ * Pushes a new include on top of the include stack
+ *
+ * Returns 0 in case of error, the index in the stack otherwise
+ */
+static int
+xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt,
+ xmlRelaxNGIncludePtr value)
+{
+ if (ctxt->incTab == NULL) {
+ ctxt->incMax = 4;
+ ctxt->incNr = 0;
+ ctxt->incTab =
+ (xmlRelaxNGIncludePtr *) xmlMalloc(ctxt->incMax *
+ sizeof(ctxt->incTab[0]));
+ if (ctxt->incTab == NULL) {
+ xmlRngPErrMemory(ctxt, "allocating include\n");
+ return (0);
+ }
+ }
+ if (ctxt->incNr >= ctxt->incMax) {
+ ctxt->incMax *= 2;
+ ctxt->incTab =
+ (xmlRelaxNGIncludePtr *) xmlRealloc(ctxt->incTab,
+ ctxt->incMax *
+ sizeof(ctxt->incTab[0]));
+ if (ctxt->incTab == NULL) {
+ xmlRngPErrMemory(ctxt, "allocating include\n");
+ return (0);
+ }
+ }
+ ctxt->incTab[ctxt->incNr] = value;
+ ctxt->inc = value;
+ return (ctxt->incNr++);
+}
+
+/**
+ * xmlRelaxNGIncludePop:
+ * @ctxt: the parser context
+ *
+ * Pops the top include from the include stack
+ *
+ * Returns the include just removed
+ */
+static xmlRelaxNGIncludePtr
+xmlRelaxNGIncludePop(xmlRelaxNGParserCtxtPtr ctxt)
+{
+ xmlRelaxNGIncludePtr ret;
+
+ if (ctxt->incNr <= 0)
+ return (NULL);
+ ctxt->incNr--;
+ if (ctxt->incNr > 0)
+ ctxt->inc = ctxt->incTab[ctxt->incNr - 1];
+ else
+ ctxt->inc = NULL;
+ ret = ctxt->incTab[ctxt->incNr];
+ ctxt->incTab[ctxt->incNr] = NULL;
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGRemoveRedefine:
+ * @ctxt: the parser context
+ * @URL: the normalized URL
+ * @target: the included target
+ * @name: the define name to eliminate
+ *
+ * Applies the elimination algorithm of 4.7
+ *
+ * Returns 0 in case of error, 1 in case of success.
+ */
+static int
+xmlRelaxNGRemoveRedefine(xmlRelaxNGParserCtxtPtr ctxt,
+ const xmlChar * URL ATTRIBUTE_UNUSED,
+ xmlNodePtr target, const xmlChar * name)
+{
+ int found = 0;
+ xmlNodePtr tmp, tmp2;
+ xmlChar *name2;
+
+#ifdef DEBUG_INCLUDE
+ if (name == NULL)
+ xmlGenericError(xmlGenericErrorContext,
+ "Elimination of <include> start from %s\n", URL);
+ else
+ xmlGenericError(xmlGenericErrorContext,
+ "Elimination of <include> define %s from %s\n",
+ name, URL);
+#endif
+ tmp = target;
+ while (tmp != NULL) {
+ tmp2 = tmp->next;
+ if ((name == NULL) && (IS_RELAXNG(tmp, "start"))) {
+ found = 1;
+ xmlUnlinkNode(tmp);
+ xmlFreeNode(tmp);
+ } else if ((name != NULL) && (IS_RELAXNG(tmp, "define"))) {
+ name2 = xmlGetProp(tmp, BAD_CAST "name");
+ xmlRelaxNGNormExtSpace(name2);
+ if (name2 != NULL) {
+ if (xmlStrEqual(name, name2)) {
+ found = 1;
+ xmlUnlinkNode(tmp);
+ xmlFreeNode(tmp);
+ }
+ xmlFree(name2);
+ }
+ } else if (IS_RELAXNG(tmp, "include")) {
+ xmlChar *href = NULL;
+ xmlRelaxNGDocumentPtr inc = tmp->psvi;
+
+ if ((inc != NULL) && (inc->doc != NULL) &&
+ (inc->doc->children != NULL)) {
+
+ if (xmlStrEqual
+ (inc->doc->children->name, BAD_CAST "grammar")) {
+#ifdef DEBUG_INCLUDE
+ href = xmlGetProp(tmp, BAD_CAST "href");
+#endif
+ if (xmlRelaxNGRemoveRedefine(ctxt, href,
+ inc->doc->children->
+ children, name) == 1) {
+ found = 1;
+ }
+#ifdef DEBUG_INCLUDE
+ if (href != NULL)
+ xmlFree(href);
+#endif
+ }
+ }
+ }
+ tmp = tmp2;
+ }
+ return (found);
+}
+
+/**
+ * xmlRelaxNGLoadInclude:
+ * @ctxt: the parser context
+ * @URL: the normalized URL
+ * @node: the include node.
+ * @ns: the namespace passed from the context.
+ *
+ * First lookup if the document is already loaded into the parser context,
+ * check against recursion. If not found the resource is loaded and
+ * the content is preprocessed before being returned back to the caller.
+ *
+ * Returns the xmlRelaxNGIncludePtr or NULL in case of error
+ */
+static xmlRelaxNGIncludePtr
+xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * URL,
+ xmlNodePtr node, const xmlChar * ns)
+{
+ xmlRelaxNGIncludePtr ret = NULL;
+ xmlDocPtr doc;
+ int i;
+ xmlNodePtr root, cur;
+
+#ifdef DEBUG_INCLUDE
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlRelaxNGLoadInclude(%s)\n", URL);
+#endif
+
+ /*
+ * check against recursion in the stack
+ */
+ for (i = 0; i < ctxt->incNr; i++) {
+ if (xmlStrEqual(ctxt->incTab[i]->href, URL)) {
+ xmlRngPErr(ctxt, NULL, XML_RNGP_INCLUDE_RECURSE,
+ "Detected an Include recursion for %s\n", URL,
+ NULL);
+ return (NULL);
+ }
+ }
+
+ /*
+ * load the document
+ */
+ doc = xmlReadFile((const char *) URL,NULL,0);
+ if (doc == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_PARSE_ERROR,
+ "xmlRelaxNG: could not load %s\n", URL, NULL);
+ return (NULL);
+ }
+#ifdef DEBUG_INCLUDE
+ xmlGenericError(xmlGenericErrorContext, "Parsed %s Okay\n", URL);
+#endif
+
+ /*
+ * Allocate the document structures and register it first.
+ */
+ ret = (xmlRelaxNGIncludePtr) xmlMalloc(sizeof(xmlRelaxNGInclude));
+ if (ret == NULL) {
+ xmlRngPErrMemory(ctxt, "allocating include\n");
+ xmlFreeDoc(doc);
+ return (NULL);
+ }
+ memset(ret, 0, sizeof(xmlRelaxNGInclude));
+ ret->doc = doc;
+ ret->href = xmlStrdup(URL);
+ ret->next = ctxt->includes;
+ ctxt->includes = ret;
+
+ /*
+ * transmit the ns if needed
+ */
+ if (ns != NULL) {
+ root = xmlDocGetRootElement(doc);
+ if (root != NULL) {
+ if (xmlHasProp(root, BAD_CAST "ns") == NULL) {
+ xmlSetProp(root, BAD_CAST "ns", ns);
+ }
+ }
+ }
+
+ /*
+ * push it on the stack
+ */
+ xmlRelaxNGIncludePush(ctxt, ret);
+
+ /*
+ * Some preprocessing of the document content, this include recursing
+ * in the include stack.
+ */
+#ifdef DEBUG_INCLUDE
+ xmlGenericError(xmlGenericErrorContext, "cleanup of %s\n", URL);
+#endif
+
+ doc = xmlRelaxNGCleanupDoc(ctxt, doc);
+ if (doc == NULL) {
+ ctxt->inc = NULL;
+ return (NULL);
+ }
+
+ /*
+ * Pop up the include from the stack
+ */
+ xmlRelaxNGIncludePop(ctxt);
+
+#ifdef DEBUG_INCLUDE
+ xmlGenericError(xmlGenericErrorContext, "Checking of %s\n", URL);
+#endif
+ /*
+ * Check that the top element is a grammar
+ */
+ root = xmlDocGetRootElement(doc);
+ if (root == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_EMPTY,
+ "xmlRelaxNG: included document is empty %s\n", URL,
+ NULL);
+ return (NULL);
+ }
+ if (!IS_RELAXNG(root, "grammar")) {
+ xmlRngPErr(ctxt, node, XML_RNGP_GRAMMAR_MISSING,
+ "xmlRelaxNG: included document %s root is not a grammar\n",
+ URL, NULL);
+ return (NULL);
+ }
+
+ /*
+ * Elimination of redefined rules in the include.
+ */
+ cur = node->children;
+ while (cur != NULL) {
+ if (IS_RELAXNG(cur, "start")) {
+ int found = 0;
+
+ found =
+ xmlRelaxNGRemoveRedefine(ctxt, URL, root->children, NULL);
+ if (!found) {
+ xmlRngPErr(ctxt, node, XML_RNGP_START_MISSING,
+ "xmlRelaxNG: include %s has a start but not the included grammar\n",
+ URL, NULL);
+ }
+ } else if (IS_RELAXNG(cur, "define")) {
+ xmlChar *name;
+
+ name = xmlGetProp(cur, BAD_CAST "name");
+ if (name == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_NAME_MISSING,
+ "xmlRelaxNG: include %s has define without name\n",
+ URL, NULL);
+ } else {
+ int found;
+
+ xmlRelaxNGNormExtSpace(name);
+ found = xmlRelaxNGRemoveRedefine(ctxt, URL,
+ root->children, name);
+ if (!found) {
+ xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_MISSING,
+ "xmlRelaxNG: include %s has a define %s but not the included grammar\n",
+ URL, name);
+ }
+ xmlFree(name);
+ }
+ }
+ cur = cur->next;
+ }
+
+
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGValidErrorPush:
+ * @ctxt: the validation context
+ * @err: the error code
+ * @arg1: the first string argument
+ * @arg2: the second string argument
+ * @dup: arg need to be duplicated
+ *
+ * Pushes a new error on top of the error stack
+ *
+ * Returns 0 in case of error, the index in the stack otherwise
+ */
+static int
+xmlRelaxNGValidErrorPush(xmlRelaxNGValidCtxtPtr ctxt,
+ xmlRelaxNGValidErr err, const xmlChar * arg1,
+ const xmlChar * arg2, int dup)
+{
+ xmlRelaxNGValidErrorPtr cur;
+
+#ifdef DEBUG_ERROR
+ xmlGenericError(xmlGenericErrorContext,
+ "Pushing error %d at %d on stack\n", err, ctxt->errNr);
+#endif
+ if (ctxt->errTab == NULL) {
+ ctxt->errMax = 8;
+ ctxt->errNr = 0;
+ ctxt->errTab =
+ (xmlRelaxNGValidErrorPtr) xmlMalloc(ctxt->errMax *
+ sizeof
+ (xmlRelaxNGValidError));
+ if (ctxt->errTab == NULL) {
+ xmlRngVErrMemory(ctxt, "pushing error\n");
+ return (0);
+ }
+ ctxt->err = NULL;
+ }
+ if (ctxt->errNr >= ctxt->errMax) {
+ ctxt->errMax *= 2;
+ ctxt->errTab =
+ (xmlRelaxNGValidErrorPtr) xmlRealloc(ctxt->errTab,
+ ctxt->errMax *
+ sizeof
+ (xmlRelaxNGValidError));
+ if (ctxt->errTab == NULL) {
+ xmlRngVErrMemory(ctxt, "pushing error\n");
+ return (0);
+ }
+ ctxt->err = &ctxt->errTab[ctxt->errNr - 1];
+ }
+ if ((ctxt->err != NULL) && (ctxt->state != NULL) &&
+ (ctxt->err->node == ctxt->state->node) && (ctxt->err->err == err))
+ return (ctxt->errNr);
+ cur = &ctxt->errTab[ctxt->errNr];
+ cur->err = err;
+ if (dup) {
+ cur->arg1 = xmlStrdup(arg1);
+ cur->arg2 = xmlStrdup(arg2);
+ cur->flags = ERROR_IS_DUP;
+ } else {
+ cur->arg1 = arg1;
+ cur->arg2 = arg2;
+ cur->flags = 0;
+ }
+ if (ctxt->state != NULL) {
+ cur->node = ctxt->state->node;
+ cur->seq = ctxt->state->seq;
+ } else {
+ cur->node = NULL;
+ cur->seq = NULL;
+ }
+ ctxt->err = cur;
+ return (ctxt->errNr++);
+}
+
+/**
+ * xmlRelaxNGValidErrorPop:
+ * @ctxt: the validation context
+ *
+ * Pops the top error from the error stack
+ */
+static void
+xmlRelaxNGValidErrorPop(xmlRelaxNGValidCtxtPtr ctxt)
+{
+ xmlRelaxNGValidErrorPtr cur;
+
+ if (ctxt->errNr <= 0) {
+ ctxt->err = NULL;
+ return;
+ }
+ ctxt->errNr--;
+ if (ctxt->errNr > 0)
+ ctxt->err = &ctxt->errTab[ctxt->errNr - 1];
+ else
+ ctxt->err = NULL;
+ cur = &ctxt->errTab[ctxt->errNr];
+ if (cur->flags & ERROR_IS_DUP) {
+ if (cur->arg1 != NULL)
+ xmlFree((xmlChar *) cur->arg1);
+ cur->arg1 = NULL;
+ if (cur->arg2 != NULL)
+ xmlFree((xmlChar *) cur->arg2);
+ cur->arg2 = NULL;
+ cur->flags = 0;
+ }
+}
+
+/**
+ * xmlRelaxNGDocumentPush:
+ * @ctxt: the parser context
+ * @value: the element doc
+ *
+ * Pushes a new doc on top of the doc stack
+ *
+ * Returns 0 in case of error, the index in the stack otherwise
+ */
+static int
+xmlRelaxNGDocumentPush(xmlRelaxNGParserCtxtPtr ctxt,
+ xmlRelaxNGDocumentPtr value)
+{
+ if (ctxt->docTab == NULL) {
+ ctxt->docMax = 4;
+ ctxt->docNr = 0;
+ ctxt->docTab =
+ (xmlRelaxNGDocumentPtr *) xmlMalloc(ctxt->docMax *
+ sizeof(ctxt->docTab[0]));
+ if (ctxt->docTab == NULL) {
+ xmlRngPErrMemory(ctxt, "adding document\n");
+ return (0);
+ }
+ }
+ if (ctxt->docNr >= ctxt->docMax) {
+ ctxt->docMax *= 2;
+ ctxt->docTab =
+ (xmlRelaxNGDocumentPtr *) xmlRealloc(ctxt->docTab,
+ ctxt->docMax *
+ sizeof(ctxt->docTab[0]));
+ if (ctxt->docTab == NULL) {
+ xmlRngPErrMemory(ctxt, "adding document\n");
+ return (0);
+ }
+ }
+ ctxt->docTab[ctxt->docNr] = value;
+ ctxt->doc = value;
+ return (ctxt->docNr++);
+}
+
+/**
+ * xmlRelaxNGDocumentPop:
+ * @ctxt: the parser context
+ *
+ * Pops the top doc from the doc stack
+ *
+ * Returns the doc just removed
+ */
+static xmlRelaxNGDocumentPtr
+xmlRelaxNGDocumentPop(xmlRelaxNGParserCtxtPtr ctxt)
+{
+ xmlRelaxNGDocumentPtr ret;
+
+ if (ctxt->docNr <= 0)
+ return (NULL);
+ ctxt->docNr--;
+ if (ctxt->docNr > 0)
+ ctxt->doc = ctxt->docTab[ctxt->docNr - 1];
+ else
+ ctxt->doc = NULL;
+ ret = ctxt->docTab[ctxt->docNr];
+ ctxt->docTab[ctxt->docNr] = NULL;
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGLoadExternalRef:
+ * @ctxt: the parser context
+ * @URL: the normalized URL
+ * @ns: the inherited ns if any
+ *
+ * First lookup if the document is already loaded into the parser context,
+ * check against recursion. If not found the resource is loaded and
+ * the content is preprocessed before being returned back to the caller.
+ *
+ * Returns the xmlRelaxNGDocumentPtr or NULL in case of error
+ */
+static xmlRelaxNGDocumentPtr
+xmlRelaxNGLoadExternalRef(xmlRelaxNGParserCtxtPtr ctxt,
+ const xmlChar * URL, const xmlChar * ns)
+{
+ xmlRelaxNGDocumentPtr ret = NULL;
+ xmlDocPtr doc;
+ xmlNodePtr root;
+ int i;
+
+ /*
+ * check against recursion in the stack
+ */
+ for (i = 0; i < ctxt->docNr; i++) {
+ if (xmlStrEqual(ctxt->docTab[i]->href, URL)) {
+ xmlRngPErr(ctxt, NULL, XML_RNGP_EXTERNALREF_RECURSE,
+ "Detected an externalRef recursion for %s\n", URL,
+ NULL);
+ return (NULL);
+ }
+ }
+
+ /*
+ * load the document
+ */
+ doc = xmlReadFile((const char *) URL,NULL,0);
+ if (doc == NULL) {
+ xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,
+ "xmlRelaxNG: could not load %s\n", URL, NULL);
+ return (NULL);
+ }
+
+ /*
+ * Allocate the document structures and register it first.
+ */
+ ret = (xmlRelaxNGDocumentPtr) xmlMalloc(sizeof(xmlRelaxNGDocument));
+ if (ret == NULL) {
+ xmlRngPErr(ctxt, (xmlNodePtr) doc, XML_ERR_NO_MEMORY,
+ "xmlRelaxNG: allocate memory for doc %s\n", URL, NULL);
+ xmlFreeDoc(doc);
+ return (NULL);
+ }
+ memset(ret, 0, sizeof(xmlRelaxNGDocument));
+ ret->doc = doc;
+ ret->href = xmlStrdup(URL);
+ ret->next = ctxt->documents;
+ ctxt->documents = ret;
+
+ /*
+ * transmit the ns if needed
+ */
+ if (ns != NULL) {
+ root = xmlDocGetRootElement(doc);
+ if (root != NULL) {
+ if (xmlHasProp(root, BAD_CAST "ns") == NULL) {
+ xmlSetProp(root, BAD_CAST "ns", ns);
+ }
+ }
+ }
+
+ /*
+ * push it on the stack and register it in the hash table
+ */
+ xmlRelaxNGDocumentPush(ctxt, ret);
+
+ /*
+ * Some preprocessing of the document content
+ */
+ doc = xmlRelaxNGCleanupDoc(ctxt, doc);
+ if (doc == NULL) {
+ ctxt->doc = NULL;
+ return (NULL);
+ }
+
+ xmlRelaxNGDocumentPop(ctxt);
+
+ return (ret);
+}
+
+/************************************************************************
+ * *
+ * Error functions *
+ * *
+ ************************************************************************/
+
+#define VALID_ERR(a) xmlRelaxNGAddValidError(ctxt, a, NULL, NULL, 0);
+#define VALID_ERR2(a, b) xmlRelaxNGAddValidError(ctxt, a, b, NULL, 0);
+#define VALID_ERR3(a, b, c) xmlRelaxNGAddValidError(ctxt, a, b, c, 0);
+#define VALID_ERR2P(a, b) xmlRelaxNGAddValidError(ctxt, a, b, NULL, 1);
+#define VALID_ERR3P(a, b, c) xmlRelaxNGAddValidError(ctxt, a, b, c, 1);
+
+static const char *
+xmlRelaxNGDefName(xmlRelaxNGDefinePtr def)
+{
+ if (def == NULL)
+ return ("none");
+ switch (def->type) {
+ case XML_RELAXNG_EMPTY:
+ return ("empty");
+ case XML_RELAXNG_NOT_ALLOWED:
+ return ("notAllowed");
+ case XML_RELAXNG_EXCEPT:
+ return ("except");
+ case XML_RELAXNG_TEXT:
+ return ("text");
+ case XML_RELAXNG_ELEMENT:
+ return ("element");
+ case XML_RELAXNG_DATATYPE:
+ return ("datatype");
+ case XML_RELAXNG_VALUE:
+ return ("value");
+ case XML_RELAXNG_LIST:
+ return ("list");
+ case XML_RELAXNG_ATTRIBUTE:
+ return ("attribute");
+ case XML_RELAXNG_DEF:
+ return ("def");
+ case XML_RELAXNG_REF:
+ return ("ref");
+ case XML_RELAXNG_EXTERNALREF:
+ return ("externalRef");
+ case XML_RELAXNG_PARENTREF:
+ return ("parentRef");
+ case XML_RELAXNG_OPTIONAL:
+ return ("optional");
+ case XML_RELAXNG_ZEROORMORE:
+ return ("zeroOrMore");
+ case XML_RELAXNG_ONEORMORE:
+ return ("oneOrMore");
+ case XML_RELAXNG_CHOICE:
+ return ("choice");
+ case XML_RELAXNG_GROUP:
+ return ("group");
+ case XML_RELAXNG_INTERLEAVE:
+ return ("interleave");
+ case XML_RELAXNG_START:
+ return ("start");
+ case XML_RELAXNG_NOOP:
+ return ("noop");
+ case XML_RELAXNG_PARAM:
+ return ("param");
+ }
+ return ("unknown");
+}
+
+/**
+ * xmlRelaxNGGetErrorString:
+ * @err: the error code
+ * @arg1: the first string argument
+ * @arg2: the second string argument
+ *
+ * computes a formatted error string for the given error code and args
+ *
+ * Returns the error string, it must be deallocated by the caller
+ */
+static xmlChar *
+xmlRelaxNGGetErrorString(xmlRelaxNGValidErr err, const xmlChar * arg1,
+ const xmlChar * arg2)
+{
+ char msg[1000];
+
+ if (arg1 == NULL)
+ arg1 = BAD_CAST "";
+ if (arg2 == NULL)
+ arg2 = BAD_CAST "";
+
+ msg[0] = 0;
+ switch (err) {
+ case XML_RELAXNG_OK:
+ return (NULL);
+ case XML_RELAXNG_ERR_MEMORY:
+ return (xmlCharStrdup("out of memory\n"));
+ case XML_RELAXNG_ERR_TYPE:
+ snprintf(msg, 1000, "failed to validate type %s\n", arg1);
+ break;
+ case XML_RELAXNG_ERR_TYPEVAL:
+ snprintf(msg, 1000, "Type %s doesn't allow value '%s'\n", arg1,
+ arg2);
+ break;
+ case XML_RELAXNG_ERR_DUPID:
+ snprintf(msg, 1000, "ID %s redefined\n", arg1);
+ break;
+ case XML_RELAXNG_ERR_TYPECMP:
+ snprintf(msg, 1000, "failed to compare type %s\n", arg1);
+ break;
+ case XML_RELAXNG_ERR_NOSTATE:
+ return (xmlCharStrdup("Internal error: no state\n"));
+ case XML_RELAXNG_ERR_NODEFINE:
+ return (xmlCharStrdup("Internal error: no define\n"));
+ case XML_RELAXNG_ERR_INTERNAL:
+ snprintf(msg, 1000, "Internal error: %s\n", arg1);
+ break;
+ case XML_RELAXNG_ERR_LISTEXTRA:
+ snprintf(msg, 1000, "Extra data in list: %s\n", arg1);
+ break;
+ case XML_RELAXNG_ERR_INTERNODATA:
+ return (xmlCharStrdup
+ ("Internal: interleave block has no data\n"));
+ case XML_RELAXNG_ERR_INTERSEQ:
+ return (xmlCharStrdup("Invalid sequence in interleave\n"));
+ case XML_RELAXNG_ERR_INTEREXTRA:
+ snprintf(msg, 1000, "Extra element %s in interleave\n", arg1);
+ break;
+ case XML_RELAXNG_ERR_ELEMNAME:
+ snprintf(msg, 1000, "Expecting element %s, got %s\n", arg1,
+ arg2);
+ break;
+ case XML_RELAXNG_ERR_ELEMNONS:
+ snprintf(msg, 1000, "Expecting a namespace for element %s\n",
+ arg1);
+ break;
+ case XML_RELAXNG_ERR_ELEMWRONGNS:
+ snprintf(msg, 1000,
+ "Element %s has wrong namespace: expecting %s\n", arg1,
+ arg2);
+ break;
+ case XML_RELAXNG_ERR_ELEMWRONG:
+ snprintf(msg, 1000, "Did not expect element %s there\n", arg1);
+ break;
+ case XML_RELAXNG_ERR_TEXTWRONG:
+ snprintf(msg, 1000,
+ "Did not expect text in element %s content\n", arg1);
+ break;
+ case XML_RELAXNG_ERR_ELEMEXTRANS:
+ snprintf(msg, 1000, "Expecting no namespace for element %s\n",
+ arg1);
+ break;
+ case XML_RELAXNG_ERR_ELEMNOTEMPTY:
+ snprintf(msg, 1000, "Expecting element %s to be empty\n", arg1);
+ break;
+ case XML_RELAXNG_ERR_NOELEM:
+ snprintf(msg, 1000, "Expecting an element %s, got nothing\n",
+ arg1);
+ break;
+ case XML_RELAXNG_ERR_NOTELEM:
+ return (xmlCharStrdup("Expecting an element got text\n"));
+ case XML_RELAXNG_ERR_ATTRVALID:
+ snprintf(msg, 1000, "Element %s failed to validate attributes\n",
+ arg1);
+ break;
+ case XML_RELAXNG_ERR_CONTENTVALID:
+ snprintf(msg, 1000, "Element %s failed to validate content\n",
+ arg1);
+ break;
+ case XML_RELAXNG_ERR_EXTRACONTENT:
+ snprintf(msg, 1000, "Element %s has extra content: %s\n",
+ arg1, arg2);
+ break;
+ case XML_RELAXNG_ERR_INVALIDATTR:
+ snprintf(msg, 1000, "Invalid attribute %s for element %s\n",
+ arg1, arg2);
+ break;
+ case XML_RELAXNG_ERR_LACKDATA:
+ snprintf(msg, 1000, "Datatype element %s contains no data\n",
+ arg1);
+ break;
+ case XML_RELAXNG_ERR_DATAELEM:
+ snprintf(msg, 1000, "Datatype element %s has child elements\n",
+ arg1);
+ break;
+ case XML_RELAXNG_ERR_VALELEM:
+ snprintf(msg, 1000, "Value element %s has child elements\n",
+ arg1);
+ break;
+ case XML_RELAXNG_ERR_LISTELEM:
+ snprintf(msg, 1000, "List element %s has child elements\n",
+ arg1);
+ break;
+ case XML_RELAXNG_ERR_DATATYPE:
+ snprintf(msg, 1000, "Error validating datatype %s\n", arg1);
+ break;
+ case XML_RELAXNG_ERR_VALUE:
+ snprintf(msg, 1000, "Error validating value %s\n", arg1);
+ break;
+ case XML_RELAXNG_ERR_LIST:
+ return (xmlCharStrdup("Error validating list\n"));
+ case XML_RELAXNG_ERR_NOGRAMMAR:
+ return (xmlCharStrdup("No top grammar defined\n"));
+ case XML_RELAXNG_ERR_EXTRADATA:
+ return (xmlCharStrdup("Extra data in the document\n"));
+ default:
+ return (xmlCharStrdup("Unknown error !\n"));
+ }
+ if (msg[0] == 0) {
+ snprintf(msg, 1000, "Unknown error code %d\n", err);
+ }
+ msg[1000 - 1] = 0;
+ return (xmlStrdup((xmlChar *) msg));
+}
+
+/**
+ * xmlRelaxNGShowValidError:
+ * @ctxt: the validation context
+ * @err: the error number
+ * @node: the node
+ * @child: the node child generating the problem.
+ * @arg1: the first argument
+ * @arg2: the second argument
+ *
+ * Show a validation error.
+ */
+static void
+xmlRelaxNGShowValidError(xmlRelaxNGValidCtxtPtr ctxt,
+ xmlRelaxNGValidErr err, xmlNodePtr node,
+ xmlNodePtr child, const xmlChar * arg1,
+ const xmlChar * arg2)
+{
+ xmlChar *msg;
+
+ if (ctxt->flags & FLAGS_NOERROR)
+ return;
+
+#ifdef DEBUG_ERROR
+ xmlGenericError(xmlGenericErrorContext, "Show error %d\n", err);
+#endif
+ msg = xmlRelaxNGGetErrorString(err, arg1, arg2);
+ if (msg == NULL)
+ return;
+
+ if (ctxt->errNo == XML_RELAXNG_OK)
+ ctxt->errNo = err;
+ xmlRngVErr(ctxt, (child == NULL ? node : child), err,
+ (const char *) msg, arg1, arg2);
+ xmlFree(msg);
+}
+
+/**
+ * xmlRelaxNGPopErrors:
+ * @ctxt: the validation context
+ * @level: the error level in the stack
+ *
+ * pop and discard all errors until the given level is reached
+ */
+static void
+xmlRelaxNGPopErrors(xmlRelaxNGValidCtxtPtr ctxt, int level)
+{
+ int i;
+ xmlRelaxNGValidErrorPtr err;
+
+#ifdef DEBUG_ERROR
+ xmlGenericError(xmlGenericErrorContext,
+ "Pop errors till level %d\n", level);
+#endif
+ for (i = level; i < ctxt->errNr; i++) {
+ err = &ctxt->errTab[i];
+ if (err->flags & ERROR_IS_DUP) {
+ if (err->arg1 != NULL)
+ xmlFree((xmlChar *) err->arg1);
+ err->arg1 = NULL;
+ if (err->arg2 != NULL)
+ xmlFree((xmlChar *) err->arg2);
+ err->arg2 = NULL;
+ err->flags = 0;
+ }
+ }
+ ctxt->errNr = level;
+ if (ctxt->errNr <= 0)
+ ctxt->err = NULL;
+}
+
+/**
+ * xmlRelaxNGDumpValidError:
+ * @ctxt: the validation context
+ *
+ * Show all validation error over a given index.
+ */
+static void
+xmlRelaxNGDumpValidError(xmlRelaxNGValidCtxtPtr ctxt)
+{
+ int i, j, k;
+ xmlRelaxNGValidErrorPtr err, dup;
+
+#ifdef DEBUG_ERROR
+ xmlGenericError(xmlGenericErrorContext,
+ "Dumping error stack %d errors\n", ctxt->errNr);
+#endif
+ for (i = 0, k = 0; i < ctxt->errNr; i++) {
+ err = &ctxt->errTab[i];
+ if (k < MAX_ERROR) {
+ for (j = 0; j < i; j++) {
+ dup = &ctxt->errTab[j];
+ if ((err->err == dup->err) && (err->node == dup->node) &&
+ (xmlStrEqual(err->arg1, dup->arg1)) &&
+ (xmlStrEqual(err->arg2, dup->arg2))) {
+ goto skip;
+ }
+ }
+ xmlRelaxNGShowValidError(ctxt, err->err, err->node, err->seq,
+ err->arg1, err->arg2);
+ k++;
+ }
+ skip:
+ if (err->flags & ERROR_IS_DUP) {
+ if (err->arg1 != NULL)
+ xmlFree((xmlChar *) err->arg1);
+ err->arg1 = NULL;
+ if (err->arg2 != NULL)
+ xmlFree((xmlChar *) err->arg2);
+ err->arg2 = NULL;
+ err->flags = 0;
+ }
+ }
+ ctxt->errNr = 0;
+}
+
+/**
+ * xmlRelaxNGAddValidError:
+ * @ctxt: the validation context
+ * @err: the error number
+ * @arg1: the first argument
+ * @arg2: the second argument
+ * @dup: need to dup the args
+ *
+ * Register a validation error, either generating it if it's sure
+ * or stacking it for later handling if unsure.
+ */
+static void
+xmlRelaxNGAddValidError(xmlRelaxNGValidCtxtPtr ctxt,
+ xmlRelaxNGValidErr err, const xmlChar * arg1,
+ const xmlChar * arg2, int dup)
+{
+ if (ctxt == NULL)
+ return;
+ if (ctxt->flags & FLAGS_NOERROR)
+ return;
+
+#ifdef DEBUG_ERROR
+ xmlGenericError(xmlGenericErrorContext, "Adding error %d\n", err);
+#endif
+ /*
+ * generate the error directly
+ */
+ if (((ctxt->flags & FLAGS_IGNORABLE) == 0) ||
+ (ctxt->flags & FLAGS_NEGATIVE)) {
+ xmlNodePtr node, seq;
+
+ /*
+ * Flush first any stacked error which might be the
+ * real cause of the problem.
+ */
+ if (ctxt->errNr != 0)
+ xmlRelaxNGDumpValidError(ctxt);
+ if (ctxt->state != NULL) {
+ node = ctxt->state->node;
+ seq = ctxt->state->seq;
+ } else {
+ node = seq = NULL;
+ }
+ xmlRelaxNGShowValidError(ctxt, err, node, seq, arg1, arg2);
+ }
+ /*
+ * Stack the error for later processing if needed
+ */
+ else {
+ xmlRelaxNGValidErrorPush(ctxt, err, arg1, arg2, dup);
+ }
+}
+
+
+/************************************************************************
+ * *
+ * Type library hooks *
+ * *
+ ************************************************************************/
+static xmlChar *xmlRelaxNGNormalize(xmlRelaxNGValidCtxtPtr ctxt,
+ const xmlChar * str);
+
+/**
+ * xmlRelaxNGSchemaTypeHave:
+ * @data: data needed for the library
+ * @type: the type name
+ *
+ * Check if the given type is provided by
+ * the W3C XMLSchema Datatype library.
+ *
+ * Returns 1 if yes, 0 if no and -1 in case of error.
+ */
+static int
+xmlRelaxNGSchemaTypeHave(void *data ATTRIBUTE_UNUSED, const xmlChar * type)
+{
+ xmlSchemaTypePtr typ;
+
+ if (type == NULL)
+ return (-1);
+ typ = xmlSchemaGetPredefinedType(type,
+ BAD_CAST
+ "http://www.w3.org/2001/XMLSchema");
+ if (typ == NULL)
+ return (0);
+ return (1);
+}
+
+/**
+ * xmlRelaxNGSchemaTypeCheck:
+ * @data: data needed for the library
+ * @type: the type name
+ * @value: the value to check
+ * @node: the node
+ *
+ * Check if the given type and value are validated by
+ * the W3C XMLSchema Datatype library.
+ *
+ * Returns 1 if yes, 0 if no and -1 in case of error.
+ */
+static int
+xmlRelaxNGSchemaTypeCheck(void *data ATTRIBUTE_UNUSED,
+ const xmlChar * type,
+ const xmlChar * value,
+ void **result, xmlNodePtr node)
+{
+ xmlSchemaTypePtr typ;
+ int ret;
+
+ if ((type == NULL) || (value == NULL))
+ return (-1);
+ typ = xmlSchemaGetPredefinedType(type,
+ BAD_CAST
+ "http://www.w3.org/2001/XMLSchema");
+ if (typ == NULL)
+ return (-1);
+ ret = xmlSchemaValPredefTypeNode(typ, value,
+ (xmlSchemaValPtr *) result, node);
+ if (ret == 2) /* special ID error code */
+ return (2);
+ if (ret == 0)
+ return (1);
+ if (ret > 0)
+ return (0);
+ return (-1);
+}
+
+/**
+ * xmlRelaxNGSchemaFacetCheck:
+ * @data: data needed for the library
+ * @type: the type name
+ * @facet: the facet name
+ * @val: the facet value
+ * @strval: the string value
+ * @value: the value to check
+ *
+ * Function provided by a type library to check a value facet
+ *
+ * Returns 1 if yes, 0 if no and -1 in case of error.
+ */
+static int
+xmlRelaxNGSchemaFacetCheck(void *data ATTRIBUTE_UNUSED,
+ const xmlChar * type, const xmlChar * facetname,
+ const xmlChar * val, const xmlChar * strval,
+ void *value)
+{
+ xmlSchemaFacetPtr facet;
+ xmlSchemaTypePtr typ;
+ int ret;
+
+ if ((type == NULL) || (strval == NULL))
+ return (-1);
+ typ = xmlSchemaGetPredefinedType(type,
+ BAD_CAST
+ "http://www.w3.org/2001/XMLSchema");
+ if (typ == NULL)
+ return (-1);
+
+ facet = xmlSchemaNewFacet();
+ if (facet == NULL)
+ return (-1);
+
+ if (xmlStrEqual(facetname, BAD_CAST "minInclusive")) {
+ facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
+ } else if (xmlStrEqual(facetname, BAD_CAST "minExclusive")) {
+ facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
+ } else if (xmlStrEqual(facetname, BAD_CAST "maxInclusive")) {
+ facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
+ } else if (xmlStrEqual(facetname, BAD_CAST "maxExclusive")) {
+ facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
+ } else if (xmlStrEqual(facetname, BAD_CAST "totalDigits")) {
+ facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
+ } else if (xmlStrEqual(facetname, BAD_CAST "fractionDigits")) {
+ facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
+ } else if (xmlStrEqual(facetname, BAD_CAST "pattern")) {
+ facet->type = XML_SCHEMA_FACET_PATTERN;
+ } else if (xmlStrEqual(facetname, BAD_CAST "enumeration")) {
+ facet->type = XML_SCHEMA_FACET_ENUMERATION;
+ } else if (xmlStrEqual(facetname, BAD_CAST "whiteSpace")) {
+ facet->type = XML_SCHEMA_FACET_WHITESPACE;
+ } else if (xmlStrEqual(facetname, BAD_CAST "length")) {
+ facet->type = XML_SCHEMA_FACET_LENGTH;
+ } else if (xmlStrEqual(facetname, BAD_CAST "maxLength")) {
+ facet->type = XML_SCHEMA_FACET_MAXLENGTH;
+ } else if (xmlStrEqual(facetname, BAD_CAST "minLength")) {
+ facet->type = XML_SCHEMA_FACET_MINLENGTH;
+ } else {
+ xmlSchemaFreeFacet(facet);
+ return (-1);
+ }
+ facet->value = val;
+ ret = xmlSchemaCheckFacet(facet, typ, NULL, type);
+ if (ret != 0) {
+ xmlSchemaFreeFacet(facet);
+ return (-1);
+ }
+ ret = xmlSchemaValidateFacet(typ, facet, strval, value);
+ xmlSchemaFreeFacet(facet);
+ if (ret != 0)
+ return (-1);
+ return (0);
+}
+
+/**
+ * xmlRelaxNGSchemaFreeValue:
+ * @data: data needed for the library
+ * @value: the value to free
+ *
+ * Function provided by a type library to free a Schemas value
+ *
+ * Returns 1 if yes, 0 if no and -1 in case of error.
+ */
+static void
+xmlRelaxNGSchemaFreeValue(void *data ATTRIBUTE_UNUSED, void *value)
+{
+ xmlSchemaFreeValue(value);
+}
+
+/**
+ * xmlRelaxNGSchemaTypeCompare:
+ * @data: data needed for the library
+ * @type: the type name
+ * @value1: the first value
+ * @value2: the second value
+ *
+ * Compare two values for equality accordingly a type from the W3C XMLSchema
+ * Datatype library.
+ *
+ * Returns 1 if equal, 0 if no and -1 in case of error.
+ */
+static int
+xmlRelaxNGSchemaTypeCompare(void *data ATTRIBUTE_UNUSED,
+ const xmlChar * type,
+ const xmlChar * value1,
+ xmlNodePtr ctxt1,
+ void *comp1,
+ const xmlChar * value2, xmlNodePtr ctxt2)
+{
+ int ret;
+ xmlSchemaTypePtr typ;
+ xmlSchemaValPtr res1 = NULL, res2 = NULL;
+
+ if ((type == NULL) || (value1 == NULL) || (value2 == NULL))
+ return (-1);
+ typ = xmlSchemaGetPredefinedType(type,
+ BAD_CAST
+ "http://www.w3.org/2001/XMLSchema");
+ if (typ == NULL)
+ return (-1);
+ if (comp1 == NULL) {
+ ret = xmlSchemaValPredefTypeNode(typ, value1, &res1, ctxt1);
+ if (ret != 0)
+ return (-1);
+ if (res1 == NULL)
+ return (-1);
+ } else {
+ res1 = (xmlSchemaValPtr) comp1;
+ }
+ ret = xmlSchemaValPredefTypeNode(typ, value2, &res2, ctxt2);
+ if (ret != 0) {
+ if ((comp1 == NULL) && (res1 != NULL))
+ xmlSchemaFreeValue(res1);
+ return (-1);
+ }
+ if (res1 == NULL) {
+ return (-1);
+ }
+ ret = xmlSchemaCompareValues(res1, res2);
+ if (res1 != (xmlSchemaValPtr) comp1)
+ xmlSchemaFreeValue(res1);
+ xmlSchemaFreeValue(res2);
+ if (ret == -2)
+ return (-1);
+ if (ret == 0)
+ return (1);
+ return (0);
+}
+
+/**
+ * xmlRelaxNGDefaultTypeHave:
+ * @data: data needed for the library
+ * @type: the type name
+ *
+ * Check if the given type is provided by
+ * the default datatype library.
+ *
+ * Returns 1 if yes, 0 if no and -1 in case of error.
+ */
+static int
+xmlRelaxNGDefaultTypeHave(void *data ATTRIBUTE_UNUSED,
+ const xmlChar * type)
+{
+ if (type == NULL)
+ return (-1);
+ if (xmlStrEqual(type, BAD_CAST "string"))
+ return (1);
+ if (xmlStrEqual(type, BAD_CAST "token"))
+ return (1);
+ return (0);
+}
+
+/**
+ * xmlRelaxNGDefaultTypeCheck:
+ * @data: data needed for the library
+ * @type: the type name
+ * @value: the value to check
+ * @node: the node
+ *
+ * Check if the given type and value are validated by
+ * the default datatype library.
+ *
+ * Returns 1 if yes, 0 if no and -1 in case of error.
+ */
+static int
+xmlRelaxNGDefaultTypeCheck(void *data ATTRIBUTE_UNUSED,
+ const xmlChar * type ATTRIBUTE_UNUSED,
+ const xmlChar * value ATTRIBUTE_UNUSED,
+ void **result ATTRIBUTE_UNUSED,
+ xmlNodePtr node ATTRIBUTE_UNUSED)
+{
+ if (value == NULL)
+ return (-1);
+ if (xmlStrEqual(type, BAD_CAST "string"))
+ return (1);
+ if (xmlStrEqual(type, BAD_CAST "token")) {
+ return (1);
+ }
+
+ return (0);
+}
+
+/**
+ * xmlRelaxNGDefaultTypeCompare:
+ * @data: data needed for the library
+ * @type: the type name
+ * @value1: the first value
+ * @value2: the second value
+ *
+ * Compare two values accordingly a type from the default
+ * datatype library.
+ *
+ * Returns 1 if yes, 0 if no and -1 in case of error.
+ */
+static int
+xmlRelaxNGDefaultTypeCompare(void *data ATTRIBUTE_UNUSED,
+ const xmlChar * type,
+ const xmlChar * value1,
+ xmlNodePtr ctxt1 ATTRIBUTE_UNUSED,
+ void *comp1 ATTRIBUTE_UNUSED,
+ const xmlChar * value2,
+ xmlNodePtr ctxt2 ATTRIBUTE_UNUSED)
+{
+ int ret = -1;
+
+ if (xmlStrEqual(type, BAD_CAST "string")) {
+ ret = xmlStrEqual(value1, value2);
+ } else if (xmlStrEqual(type, BAD_CAST "token")) {
+ if (!xmlStrEqual(value1, value2)) {
+ xmlChar *nval, *nvalue;
+
+ /*
+ * TODO: trivial optimizations are possible by
+ * computing at compile-time
+ */
+ nval = xmlRelaxNGNormalize(NULL, value1);
+ nvalue = xmlRelaxNGNormalize(NULL, value2);
+
+ if ((nval == NULL) || (nvalue == NULL))
+ ret = -1;
+ else if (xmlStrEqual(nval, nvalue))
+ ret = 1;
+ else
+ ret = 0;
+ if (nval != NULL)
+ xmlFree(nval);
+ if (nvalue != NULL)
+ xmlFree(nvalue);
+ } else
+ ret = 1;
+ }
+ return (ret);
+}
+
+static int xmlRelaxNGTypeInitialized = 0;
+static xmlHashTablePtr xmlRelaxNGRegisteredTypes = NULL;
+
+/**
+ * xmlRelaxNGFreeTypeLibrary:
+ * @lib: the type library structure
+ * @namespace: the URI bound to the library
+ *
+ * Free the structure associated to the type library
+ */
+static void
+xmlRelaxNGFreeTypeLibrary(xmlRelaxNGTypeLibraryPtr lib,
+ const xmlChar * namespace ATTRIBUTE_UNUSED)
+{
+ if (lib == NULL)
+ return;
+ if (lib->namespace != NULL)
+ xmlFree((xmlChar *) lib->namespace);
+ xmlFree(lib);
+}
+
+/**
+ * xmlRelaxNGRegisterTypeLibrary:
+ * @namespace: the URI bound to the library
+ * @data: data associated to the library
+ * @have: the provide function
+ * @check: the checking function
+ * @comp: the comparison function
+ *
+ * Register a new type library
+ *
+ * Returns 0 in case of success and -1 in case of error.
+ */
+static int
+xmlRelaxNGRegisterTypeLibrary(const xmlChar * namespace, void *data,
+ xmlRelaxNGTypeHave have,
+ xmlRelaxNGTypeCheck check,
+ xmlRelaxNGTypeCompare comp,
+ xmlRelaxNGFacetCheck facet,
+ xmlRelaxNGTypeFree freef)
+{
+ xmlRelaxNGTypeLibraryPtr lib;
+ int ret;
+
+ if ((xmlRelaxNGRegisteredTypes == NULL) || (namespace == NULL) ||
+ (check == NULL) || (comp == NULL))
+ return (-1);
+ if (xmlHashLookup(xmlRelaxNGRegisteredTypes, namespace) != NULL) {
+ xmlGenericError(xmlGenericErrorContext,
+ "Relax-NG types library '%s' already registered\n",
+ namespace);
+ return (-1);
+ }
+ lib =
+ (xmlRelaxNGTypeLibraryPtr)
+ xmlMalloc(sizeof(xmlRelaxNGTypeLibrary));
+ if (lib == NULL) {
+ xmlRngVErrMemory(NULL, "adding types library\n");
+ return (-1);
+ }
+ memset(lib, 0, sizeof(xmlRelaxNGTypeLibrary));
+ lib->namespace = xmlStrdup(namespace);
+ lib->data = data;
+ lib->have = have;
+ lib->comp = comp;
+ lib->check = check;
+ lib->facet = facet;
+ lib->freef = freef;
+ ret = xmlHashAddEntry(xmlRelaxNGRegisteredTypes, namespace, lib);
+ if (ret < 0) {
+ xmlGenericError(xmlGenericErrorContext,
+ "Relax-NG types library failed to register '%s'\n",
+ namespace);
+ xmlRelaxNGFreeTypeLibrary(lib, namespace);
+ return (-1);
+ }
+ return (0);
+}
+
+/**
+ * xmlRelaxNGInitTypes:
+ *
+ * Initilize the default type libraries.
+ *
+ * Returns 0 in case of success and -1 in case of error.
+ */
+int
+xmlRelaxNGInitTypes(void)
+{
+ if (xmlRelaxNGTypeInitialized != 0)
+ return (0);
+ xmlRelaxNGRegisteredTypes = xmlHashCreate(10);
+ if (xmlRelaxNGRegisteredTypes == NULL) {
+ xmlGenericError(xmlGenericErrorContext,
+ "Failed to allocate sh table for Relax-NG types\n");
+ return (-1);
+ }
+ xmlRelaxNGRegisterTypeLibrary(BAD_CAST
+ "http://www.w3.org/2001/XMLSchema-datatypes",
+ NULL, xmlRelaxNGSchemaTypeHave,
+ xmlRelaxNGSchemaTypeCheck,
+ xmlRelaxNGSchemaTypeCompare,
+ xmlRelaxNGSchemaFacetCheck,
+ xmlRelaxNGSchemaFreeValue);
+ xmlRelaxNGRegisterTypeLibrary(xmlRelaxNGNs, NULL,
+ xmlRelaxNGDefaultTypeHave,
+ xmlRelaxNGDefaultTypeCheck,
+ xmlRelaxNGDefaultTypeCompare, NULL,
+ NULL);
+ xmlRelaxNGTypeInitialized = 1;
+ return (0);
+}
+
+/**
+ * xmlRelaxNGCleanupTypes:
+ *
+ * Cleanup the default Schemas type library associated to RelaxNG
+ */
+void
+xmlRelaxNGCleanupTypes(void)
+{
+ xmlSchemaCleanupTypes();
+ if (xmlRelaxNGTypeInitialized == 0)
+ return;
+ xmlHashFree(xmlRelaxNGRegisteredTypes, (xmlHashDeallocator)
+ xmlRelaxNGFreeTypeLibrary);
+ xmlRelaxNGTypeInitialized = 0;
+}
+
+/************************************************************************
+ * *
+ * Compiling element content into regexp *
+ * *
+ * Sometime the element content can be compiled into a pure regexp, *
+ * This allows a faster execution and streamability at that level *
+ * *
+ ************************************************************************/
+
+static int xmlRelaxNGTryCompile(xmlRelaxNGParserCtxtPtr ctxt,
+ xmlRelaxNGDefinePtr def);
+
+/**
+ * xmlRelaxNGIsCompileable:
+ * @define: the definition to check
+ *
+ * Check if a definition is nullable.
+ *
+ * Returns 1 if yes, 0 if no and -1 in case of error
+ */
+static int
+xmlRelaxNGIsCompileable(xmlRelaxNGDefinePtr def)
+{
+ int ret = -1;
+
+ if (def == NULL) {
+ return (-1);
+ }
+ if ((def->type != XML_RELAXNG_ELEMENT) &&
+ (def->dflags & IS_COMPILABLE))
+ return (1);
+ if ((def->type != XML_RELAXNG_ELEMENT) &&
+ (def->dflags & IS_NOT_COMPILABLE))
+ return (0);
+ switch (def->type) {
+ case XML_RELAXNG_NOOP:
+ ret = xmlRelaxNGIsCompileable(def->content);
+ break;
+ case XML_RELAXNG_TEXT:
+ case XML_RELAXNG_EMPTY:
+ ret = 1;
+ break;
+ case XML_RELAXNG_ELEMENT:
+ /*
+ * Check if the element content is compileable
+ */
+ if (((def->dflags & IS_NOT_COMPILABLE) == 0) &&
+ ((def->dflags & IS_COMPILABLE) == 0)) {
+ xmlRelaxNGDefinePtr list;
+
+ list = def->content;
+ while (list != NULL) {
+ ret = xmlRelaxNGIsCompileable(list);
+ if (ret != 1)
+ break;
+ list = list->next;
+ }
+ /*
+ * Because the routine is recursive, we must guard against
+ * discovering both COMPILABLE and NOT_COMPILABLE
+ */
+ if (ret == 0) {
+ def->dflags &= ~IS_COMPILABLE;
+ def->dflags |= IS_NOT_COMPILABLE;
+ }
+ if ((ret == 1) && !(def->dflags &= IS_NOT_COMPILABLE))
+ def->dflags |= IS_COMPILABLE;
+#ifdef DEBUG_COMPILE
+ if (ret == 1) {
+ xmlGenericError(xmlGenericErrorContext,
+ "element content for %s is compilable\n",
+ def->name);
+ } else if (ret == 0) {
+ xmlGenericError(xmlGenericErrorContext,
+ "element content for %s is not compilable\n",
+ def->name);
+ } else {
+ xmlGenericError(xmlGenericErrorContext,
+ "Problem in RelaxNGIsCompileable for element %s\n",
+ def->name);
+ }
+#endif
+ }
+ /*
+ * All elements return a compileable status unless they
+ * are generic like anyName
+ */
+ if ((def->nameClass != NULL) || (def->name == NULL))
+ ret = 0;
+ else
+ ret = 1;
+ return (ret);
+ case XML_RELAXNG_REF:
+ case XML_RELAXNG_EXTERNALREF:
+ case XML_RELAXNG_PARENTREF:
+ if (def->depth == -20) {
+ return (1);
+ } else {
+ xmlRelaxNGDefinePtr list;
+
+ def->depth = -20;
+ list = def->content;
+ while (list != NULL) {
+ ret = xmlRelaxNGIsCompileable(list);
+ if (ret != 1)
+ break;
+ list = list->next;
+ }
+ }
+ break;
+ case XML_RELAXNG_START:
+ case XML_RELAXNG_OPTIONAL:
+ case XML_RELAXNG_ZEROORMORE:
+ case XML_RELAXNG_ONEORMORE:
+ case XML_RELAXNG_CHOICE:
+ case XML_RELAXNG_GROUP:
+ case XML_RELAXNG_DEF:{
+ xmlRelaxNGDefinePtr list;
+
+ list = def->content;
+ while (list != NULL) {
+ ret = xmlRelaxNGIsCompileable(list);
+ if (ret != 1)
+ break;
+ list = list->next;
+ }
+ break;
+ }
+ case XML_RELAXNG_EXCEPT:
+ case XML_RELAXNG_ATTRIBUTE:
+ case XML_RELAXNG_INTERLEAVE:
+ case XML_RELAXNG_DATATYPE:
+ case XML_RELAXNG_LIST:
+ case XML_RELAXNG_PARAM:
+ case XML_RELAXNG_VALUE:
+ case XML_RELAXNG_NOT_ALLOWED:
+ ret = 0;
+ break;
+ }
+ if (ret == 0)
+ def->dflags |= IS_NOT_COMPILABLE;
+ if (ret == 1)
+ def->dflags |= IS_COMPILABLE;
+#ifdef DEBUG_COMPILE
+ if (ret == 1) {
+ xmlGenericError(xmlGenericErrorContext,
+ "RelaxNGIsCompileable %s : true\n",
+ xmlRelaxNGDefName(def));
+ } else if (ret == 0) {
+ xmlGenericError(xmlGenericErrorContext,
+ "RelaxNGIsCompileable %s : false\n",
+ xmlRelaxNGDefName(def));
+ } else {
+ xmlGenericError(xmlGenericErrorContext,
+ "Problem in RelaxNGIsCompileable %s\n",
+ xmlRelaxNGDefName(def));
+ }
+#endif
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGCompile:
+ * ctxt: the RelaxNG parser context
+ * @define: the definition tree to compile
+ *
+ * Compile the set of definitions, it works recursively, till the
+ * element boundaries, where it tries to compile the content if possible
+ *
+ * Returns 0 if success and -1 in case of error
+ */
+static int
+xmlRelaxNGCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def)
+{
+ int ret = 0;
+ xmlRelaxNGDefinePtr list;
+
+ if ((ctxt == NULL) || (def == NULL))
+ return (-1);
+
+ switch (def->type) {
+ case XML_RELAXNG_START:
+ if ((xmlRelaxNGIsCompileable(def) == 1) && (def->depth != -25)) {
+ xmlAutomataPtr oldam = ctxt->am;
+ xmlAutomataStatePtr oldstate = ctxt->state;
+
+ def->depth = -25;
+
+ list = def->content;
+ ctxt->am = xmlNewAutomata();
+ if (ctxt->am == NULL)
+ return (-1);
+ ctxt->state = xmlAutomataGetInitState(ctxt->am);
+ while (list != NULL) {
+ xmlRelaxNGCompile(ctxt, list);
+ list = list->next;
+ }
+ xmlAutomataSetFinalState(ctxt->am, ctxt->state);
+ def->contModel = xmlAutomataCompile(ctxt->am);
+ xmlRegexpIsDeterminist(def->contModel);
+
+ xmlFreeAutomata(ctxt->am);
+ ctxt->state = oldstate;
+ ctxt->am = oldam;
+ }
+ break;
+ case XML_RELAXNG_ELEMENT:
+ if ((ctxt->am != NULL) && (def->name != NULL)) {
+ ctxt->state = xmlAutomataNewTransition2(ctxt->am,
+ ctxt->state, NULL,
+ def->name, def->ns,
+ def);
+ }
+ if ((def->dflags & IS_COMPILABLE) && (def->depth != -25)) {
+ xmlAutomataPtr oldam = ctxt->am;
+ xmlAutomataStatePtr oldstate = ctxt->state;
+
+ def->depth = -25;
+
+ list = def->content;
+ ctxt->am = xmlNewAutomata();
+ if (ctxt->am == NULL)
+ return (-1);
+ ctxt->state = xmlAutomataGetInitState(ctxt->am);
+ while (list != NULL) {
+ xmlRelaxNGCompile(ctxt, list);
+ list = list->next;
+ }
+ xmlAutomataSetFinalState(ctxt->am, ctxt->state);
+ def->contModel = xmlAutomataCompile(ctxt->am);
+ if (!xmlRegexpIsDeterminist(def->contModel)) {
+ /*
+ * we can only use the automata if it is determinist
+ */
+ xmlRegFreeRegexp(def->contModel);
+ def->contModel = NULL;
+ }
+ xmlFreeAutomata(ctxt->am);
+ ctxt->state = oldstate;
+ ctxt->am = oldam;
+ } else {
+ xmlAutomataPtr oldam = ctxt->am;
+
+ /*
+ * we can't build the content model for this element content
+ * but it still might be possible to build it for some of its
+ * children, recurse.
+ */
+ ret = xmlRelaxNGTryCompile(ctxt, def);
+ ctxt->am = oldam;
+ }
+ break;
+ case XML_RELAXNG_NOOP:
+ ret = xmlRelaxNGCompile(ctxt, def->content);
+ break;
+ case XML_RELAXNG_OPTIONAL:{
+ xmlAutomataStatePtr oldstate = ctxt->state;
+
+ xmlRelaxNGCompile(ctxt, def->content);
+ xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
+ break;
+ }
+ case XML_RELAXNG_ZEROORMORE:{
+ xmlAutomataStatePtr oldstate;
+
+ ctxt->state =
+ xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
+ oldstate = ctxt->state;
+ list = def->content;
+ while (list != NULL) {
+ xmlRelaxNGCompile(ctxt, list);
+ list = list->next;
+ }
+ xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
+ ctxt->state =
+ xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
+ break;
+ }
+ case XML_RELAXNG_ONEORMORE:{
+ xmlAutomataStatePtr oldstate;
+
+ list = def->content;
+ while (list != NULL) {
+ xmlRelaxNGCompile(ctxt, list);
+ list = list->next;
+ }
+ oldstate = ctxt->state;
+ list = def->content;
+ while (list != NULL) {
+ xmlRelaxNGCompile(ctxt, list);
+ list = list->next;
+ }
+ xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
+ ctxt->state =
+ xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
+ break;
+ }
+ case XML_RELAXNG_CHOICE:{
+ xmlAutomataStatePtr target = NULL;
+ xmlAutomataStatePtr oldstate = ctxt->state;
+
+ list = def->content;
+ while (list != NULL) {
+ ctxt->state = oldstate;
+ ret = xmlRelaxNGCompile(ctxt, list);
+ if (ret != 0)
+ break;
+ if (target == NULL)
+ target = ctxt->state;
+ else {
+ xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
+ target);
+ }
+ list = list->next;
+ }
+ ctxt->state = target;
+
+ break;
+ }
+ case XML_RELAXNG_REF:
+ case XML_RELAXNG_EXTERNALREF:
+ case XML_RELAXNG_PARENTREF:
+ case XML_RELAXNG_GROUP:
+ case XML_RELAXNG_DEF:
+ list = def->content;
+ while (list != NULL) {
+ ret = xmlRelaxNGCompile(ctxt, list);
+ if (ret != 0)
+ break;
+ list = list->next;
+ }
+ break;
+ case XML_RELAXNG_TEXT:{
+ xmlAutomataStatePtr oldstate;
+
+ ctxt->state =
+ xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
+ oldstate = ctxt->state;
+ xmlRelaxNGCompile(ctxt, def->content);
+ xmlAutomataNewTransition(ctxt->am, ctxt->state,
+ ctxt->state, BAD_CAST "#text",
+ NULL);
+ ctxt->state =
+ xmlAutomataNewEpsilon(ctxt->am, oldstate, NULL);
+ break;
+ }
+ case XML_RELAXNG_EMPTY:
+ ctxt->state =
+ xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
+ break;
+ case XML_RELAXNG_EXCEPT:
+ case XML_RELAXNG_ATTRIBUTE:
+ case XML_RELAXNG_INTERLEAVE:
+ case XML_RELAXNG_NOT_ALLOWED:
+ case XML_RELAXNG_DATATYPE:
+ case XML_RELAXNG_LIST:
+ case XML_RELAXNG_PARAM:
+ case XML_RELAXNG_VALUE:
+ /* This should not happen and generate an internal error */
+ fprintf(stderr, "RNG internal error trying to compile %s\n",
+ xmlRelaxNGDefName(def));
+ break;
+ }
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGTryCompile:
+ * ctxt: the RelaxNG parser context
+ * @define: the definition tree to compile
+ *
+ * Try to compile the set of definitions, it works recursively,
+ * possibly ignoring parts which cannot be compiled.
+ *
+ * Returns 0 if success and -1 in case of error
+ */
+static int
+xmlRelaxNGTryCompile(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGDefinePtr def)
+{
+ int ret = 0;
+ xmlRelaxNGDefinePtr list;
+
+ if ((ctxt == NULL) || (def == NULL))
+ return (-1);
+
+ if ((def->type == XML_RELAXNG_START) ||
+ (def->type == XML_RELAXNG_ELEMENT)) {
+ ret = xmlRelaxNGIsCompileable(def);
+ if ((def->dflags & IS_COMPILABLE) && (def->depth != -25)) {
+ ctxt->am = NULL;
+ ret = xmlRelaxNGCompile(ctxt, def);
+#ifdef DEBUG_PROGRESSIVE
+ if (ret == 0) {
+ if (def->type == XML_RELAXNG_START)
+ xmlGenericError(xmlGenericErrorContext,
+ "compiled the start\n");
+ else
+ xmlGenericError(xmlGenericErrorContext,
+ "compiled element %s\n", def->name);
+ } else {
+ if (def->type == XML_RELAXNG_START)
+ xmlGenericError(xmlGenericErrorContext,
+ "failed to compile the start\n");
+ else
+ xmlGenericError(xmlGenericErrorContext,
+ "failed to compile element %s\n",
+ def->name);
+ }
+#endif
+ return (ret);
+ }
+ }
+ switch (def->type) {
+ case XML_RELAXNG_NOOP:
+ ret = xmlRelaxNGTryCompile(ctxt, def->content);
+ break;
+ case XML_RELAXNG_TEXT:
+ case XML_RELAXNG_DATATYPE:
+ case XML_RELAXNG_LIST:
+ case XML_RELAXNG_PARAM:
+ case XML_RELAXNG_VALUE:
+ case XML_RELAXNG_EMPTY:
+ case XML_RELAXNG_ELEMENT:
+ ret = 0;
+ break;
+ case XML_RELAXNG_OPTIONAL:
+ case XML_RELAXNG_ZEROORMORE:
+ case XML_RELAXNG_ONEORMORE:
+ case XML_RELAXNG_CHOICE:
+ case XML_RELAXNG_GROUP:
+ case XML_RELAXNG_DEF:
+ case XML_RELAXNG_START:
+ case XML_RELAXNG_REF:
+ case XML_RELAXNG_EXTERNALREF:
+ case XML_RELAXNG_PARENTREF:
+ list = def->content;
+ while (list != NULL) {
+ ret = xmlRelaxNGTryCompile(ctxt, list);
+ if (ret != 0)
+ break;
+ list = list->next;
+ }
+ break;
+ case XML_RELAXNG_EXCEPT:
+ case XML_RELAXNG_ATTRIBUTE:
+ case XML_RELAXNG_INTERLEAVE:
+ case XML_RELAXNG_NOT_ALLOWED:
+ ret = 0;
+ break;
+ }
+ return (ret);
+}
+
+/************************************************************************
+ * *
+ * Parsing functions *
+ * *
+ ************************************************************************/
+
+static xmlRelaxNGDefinePtr xmlRelaxNGParseAttribute(xmlRelaxNGParserCtxtPtr
+ ctxt, xmlNodePtr node);
+static xmlRelaxNGDefinePtr xmlRelaxNGParseElement(xmlRelaxNGParserCtxtPtr
+ ctxt, xmlNodePtr node);
+static xmlRelaxNGDefinePtr xmlRelaxNGParsePatterns(xmlRelaxNGParserCtxtPtr
+ ctxt, xmlNodePtr nodes,
+ int group);
+static xmlRelaxNGDefinePtr xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr
+ ctxt, xmlNodePtr node);
+static xmlRelaxNGPtr xmlRelaxNGParseDocument(xmlRelaxNGParserCtxtPtr ctxt,
+ xmlNodePtr node);
+static int xmlRelaxNGParseGrammarContent(xmlRelaxNGParserCtxtPtr ctxt,
+ xmlNodePtr nodes);
+static xmlRelaxNGDefinePtr xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr
+ ctxt, xmlNodePtr node,
+ xmlRelaxNGDefinePtr
+ def);
+static xmlRelaxNGGrammarPtr xmlRelaxNGParseGrammar(xmlRelaxNGParserCtxtPtr
+ ctxt, xmlNodePtr nodes);
+static int xmlRelaxNGElementMatch(xmlRelaxNGValidCtxtPtr ctxt,
+ xmlRelaxNGDefinePtr define,
+ xmlNodePtr elem);
+
+
+#define IS_BLANK_NODE(n) (xmlRelaxNGIsBlank((n)->content))
+
+/**
+ * xmlRelaxNGIsNullable:
+ * @define: the definition to verify
+ *
+ * Check if a definition is nullable.
+ *
+ * Returns 1 if yes, 0 if no and -1 in case of error
+ */
+static int
+xmlRelaxNGIsNullable(xmlRelaxNGDefinePtr define)
+{
+ int ret;
+
+ if (define == NULL)
+ return (-1);
+
+ if (define->dflags & IS_NULLABLE)
+ return (1);
+ if (define->dflags & IS_NOT_NULLABLE)
+ return (0);
+ switch (define->type) {
+ case XML_RELAXNG_EMPTY:
+ case XML_RELAXNG_TEXT:
+ ret = 1;
+ break;
+ case XML_RELAXNG_NOOP:
+ case XML_RELAXNG_DEF:
+ case XML_RELAXNG_REF:
+ case XML_RELAXNG_EXTERNALREF:
+ case XML_RELAXNG_PARENTREF:
+ case XML_RELAXNG_ONEORMORE:
+ ret = xmlRelaxNGIsNullable(define->content);
+ break;
+ case XML_RELAXNG_EXCEPT:
+ case XML_RELAXNG_NOT_ALLOWED:
+ case XML_RELAXNG_ELEMENT:
+ case XML_RELAXNG_DATATYPE:
+ case XML_RELAXNG_PARAM:
+ case XML_RELAXNG_VALUE:
+ case XML_RELAXNG_LIST:
+ case XML_RELAXNG_ATTRIBUTE:
+ ret = 0;
+ break;
+ case XML_RELAXNG_CHOICE:{
+ xmlRelaxNGDefinePtr list = define->content;
+
+ while (list != NULL) {
+ ret = xmlRelaxNGIsNullable(list);
+ if (ret != 0)
+ goto done;
+ list = list->next;
+ }
+ ret = 0;
+ break;
+ }
+ case XML_RELAXNG_START:
+ case XML_RELAXNG_INTERLEAVE:
+ case XML_RELAXNG_GROUP:{
+ xmlRelaxNGDefinePtr list = define->content;
+
+ while (list != NULL) {
+ ret = xmlRelaxNGIsNullable(list);
+ if (ret != 1)
+ goto done;
+ list = list->next;
+ }
+ return (1);
+ }
+ default:
+ return (-1);
+ }
+ done:
+ if (ret == 0)
+ define->dflags |= IS_NOT_NULLABLE;
+ if (ret == 1)
+ define->dflags |= IS_NULLABLE;
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGIsBlank:
+ * @str: a string
+ *
+ * Check if a string is ignorable c.f. 4.2. Whitespace
+ *
+ * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
+ */
+static int
+xmlRelaxNGIsBlank(xmlChar * str)
+{
+ if (str == NULL)
+ return (1);
+ while (*str != 0) {
+ if (!(IS_BLANK_CH(*str)))
+ return (0);
+ str++;
+ }
+ return (1);
+}
+
+/**
+ * xmlRelaxNGGetDataTypeLibrary:
+ * @ctxt: a Relax-NG parser context
+ * @node: the current data or value element
+ *
+ * Applies algorithm from 4.3. datatypeLibrary attribute
+ *
+ * Returns the datatypeLibary value or NULL if not found
+ */
+static xmlChar *
+xmlRelaxNGGetDataTypeLibrary(xmlRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
+ xmlNodePtr node)
+{
+ xmlChar *ret, *escape;
+
+ if ((IS_RELAXNG(node, "data")) || (IS_RELAXNG(node, "value"))) {
+ ret = xmlGetProp(node, BAD_CAST "datatypeLibrary");
+ if (ret != NULL) {
+ if (ret[0] == 0) {
+ xmlFree(ret);
+ return (NULL);
+ }
+ escape = xmlURIEscapeStr(ret, BAD_CAST ":/#?");
+ if (escape == NULL) {
+ return (ret);
+ }
+ xmlFree(ret);
+ return (escape);
+ }
+ }
+ node = node->parent;
+ while ((node != NULL) && (node->type == XML_ELEMENT_NODE)) {
+ ret = xmlGetProp(node, BAD_CAST "datatypeLibrary");
+ if (ret != NULL) {
+ if (ret[0] == 0) {
+ xmlFree(ret);
+ return (NULL);
+ }
+ escape = xmlURIEscapeStr(ret, BAD_CAST ":/#?");
+ if (escape == NULL) {
+ return (ret);
+ }
+ xmlFree(ret);
+ return (escape);
+ }
+ node = node->parent;
+ }
+ return (NULL);
+}
+
+/**
+ * xmlRelaxNGParseValue:
+ * @ctxt: a Relax-NG parser context
+ * @node: the data node.
+ *
+ * parse the content of a RelaxNG value node.
+ *
+ * Returns the definition pointer or NULL in case of error
+ */
+static xmlRelaxNGDefinePtr
+xmlRelaxNGParseValue(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
+{
+ xmlRelaxNGDefinePtr def = NULL;
+ xmlRelaxNGTypeLibraryPtr lib = NULL;
+ xmlChar *type;
+ xmlChar *library;
+ int success = 0;
+
+ def = xmlRelaxNGNewDefine(ctxt, node);
+ if (def == NULL)
+ return (NULL);
+ def->type = XML_RELAXNG_VALUE;
+
+ type = xmlGetProp(node, BAD_CAST "type");
+ if (type != NULL) {
+ xmlRelaxNGNormExtSpace(type);
+ if (xmlValidateNCName(type, 0)) {
+ xmlRngPErr(ctxt, node, XML_RNGP_TYPE_VALUE,
+ "value type '%s' is not an NCName\n", type, NULL);
+ }
+ library = xmlRelaxNGGetDataTypeLibrary(ctxt, node);
+ if (library == NULL)
+ library =
+ xmlStrdup(BAD_CAST "http://relaxng.org/ns/structure/1.0");
+
+ def->name = type;
+ def->ns = library;
+
+ lib = (xmlRelaxNGTypeLibraryPtr)
+ xmlHashLookup(xmlRelaxNGRegisteredTypes, library);
+ if (lib == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_TYPE_LIB,
+ "Use of unregistered type library '%s'\n", library,
+ NULL);
+ def->data = NULL;
+ } else {
+ def->data = lib;
+ if (lib->have == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_ERROR_TYPE_LIB,
+ "Internal error with type library '%s': no 'have'\n",
+ library, NULL);
+ } else {
+ success = lib->have(lib->data, def->name);
+ if (success != 1) {
+ xmlRngPErr(ctxt, node, XML_RNGP_TYPE_NOT_FOUND,
+ "Error type '%s' is not exported by type library '%s'\n",
+ def->name, library);
+ }
+ }
+ }
+ }
+ if (node->children == NULL) {
+ def->value = xmlStrdup(BAD_CAST "");
+ } else if (((node->children->type != XML_TEXT_NODE) &&
+ (node->children->type != XML_CDATA_SECTION_NODE)) ||
+ (node->children->next != NULL)) {
+ xmlRngPErr(ctxt, node, XML_RNGP_TEXT_EXPECTED,
+ "Expecting a single text value for <value>content\n",
+ NULL, NULL);
+ } else if (def != NULL) {
+ def->value = xmlNodeGetContent(node);
+ if (def->value == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_VALUE_NO_CONTENT,
+ "Element <value> has no content\n", NULL, NULL);
+ } else if ((lib != NULL) && (lib->check != NULL) && (success == 1)) {
+ void *val = NULL;
+
+ success =
+ lib->check(lib->data, def->name, def->value, &val, node);
+ if (success != 1) {
+ xmlRngPErr(ctxt, node, XML_RNGP_INVALID_VALUE,
+ "Value '%s' is not acceptable for type '%s'\n",
+ def->value, def->name);
+ } else {
+ if (val != NULL)
+ def->attrs = val;
+ }
+ }
+ }
+ return (def);
+}
+
+/**
+ * xmlRelaxNGParseData:
+ * @ctxt: a Relax-NG parser context
+ * @node: the data node.
+ *
+ * parse the content of a RelaxNG data node.
+ *
+ * Returns the definition pointer or NULL in case of error
+ */
+static xmlRelaxNGDefinePtr
+xmlRelaxNGParseData(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
+{
+ xmlRelaxNGDefinePtr def = NULL, except;
+ xmlRelaxNGDefinePtr param, lastparam = NULL;
+ xmlRelaxNGTypeLibraryPtr lib;
+ xmlChar *type;
+ xmlChar *library;
+ xmlNodePtr content;
+ int tmp;
+
+ type = xmlGetProp(node, BAD_CAST "type");
+ if (type == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_TYPE_MISSING, "data has no type\n", NULL,
+ NULL);
+ return (NULL);
+ }
+ xmlRelaxNGNormExtSpace(type);
+ if (xmlValidateNCName(type, 0)) {
+ xmlRngPErr(ctxt, node, XML_RNGP_TYPE_VALUE,
+ "data type '%s' is not an NCName\n", type, NULL);
+ }
+ library = xmlRelaxNGGetDataTypeLibrary(ctxt, node);
+ if (library == NULL)
+ library =
+ xmlStrdup(BAD_CAST "http://relaxng.org/ns/structure/1.0");
+
+ def = xmlRelaxNGNewDefine(ctxt, node);
+ if (def == NULL) {
+ xmlFree(type);
+ return (NULL);
+ }
+ def->type = XML_RELAXNG_DATATYPE;
+ def->name = type;
+ def->ns = library;
+
+ lib = (xmlRelaxNGTypeLibraryPtr)
+ xmlHashLookup(xmlRelaxNGRegisteredTypes, library);
+ if (lib == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_TYPE_LIB,
+ "Use of unregistered type library '%s'\n", library,
+ NULL);
+ def->data = NULL;
+ } else {
+ def->data = lib;
+ if (lib->have == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_ERROR_TYPE_LIB,
+ "Internal error with type library '%s': no 'have'\n",
+ library, NULL);
+ } else {
+ tmp = lib->have(lib->data, def->name);
+ if (tmp != 1) {
+ xmlRngPErr(ctxt, node, XML_RNGP_TYPE_NOT_FOUND,
+ "Error type '%s' is not exported by type library '%s'\n",
+ def->name, library);
+ } else
+ if ((xmlStrEqual
+ (library,
+ BAD_CAST
+ "http://www.w3.org/2001/XMLSchema-datatypes"))
+ && ((xmlStrEqual(def->name, BAD_CAST "IDREF"))
+ || (xmlStrEqual(def->name, BAD_CAST "IDREFS")))) {
+ ctxt->idref = 1;
+ }
+ }
+ }
+ content = node->children;
+
+ /*
+ * Handle optional params
+ */
+ while (content != NULL) {
+ if (!xmlStrEqual(content->name, BAD_CAST "param"))
+ break;
+ if (xmlStrEqual(library,
+ BAD_CAST "http://relaxng.org/ns/structure/1.0")) {
+ xmlRngPErr(ctxt, node, XML_RNGP_PARAM_FORBIDDEN,
+ "Type library '%s' does not allow type parameters\n",
+ library, NULL);
+ content = content->next;
+ while ((content != NULL) &&
+ (xmlStrEqual(content->name, BAD_CAST "param")))
+ content = content->next;
+ } else {
+ param = xmlRelaxNGNewDefine(ctxt, node);
+ if (param != NULL) {
+ param->type = XML_RELAXNG_PARAM;
+ param->name = xmlGetProp(content, BAD_CAST "name");
+ if (param->name == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_PARAM_NAME_MISSING,
+ "param has no name\n", NULL, NULL);
+ }
+ param->value = xmlNodeGetContent(content);
+ if (lastparam == NULL) {
+ def->attrs = lastparam = param;
+ } else {
+ lastparam->next = param;
+ lastparam = param;
+ }
+ if (lib != NULL) {
+ }
+ }
+ content = content->next;
+ }
+ }
+ /*
+ * Handle optional except
+ */
+ if ((content != NULL)
+ && (xmlStrEqual(content->name, BAD_CAST "except"))) {
+ xmlNodePtr child;
+ xmlRelaxNGDefinePtr tmp2, last = NULL;
+
+ except = xmlRelaxNGNewDefine(ctxt, node);
+ if (except == NULL) {
+ return (def);
+ }
+ except->type = XML_RELAXNG_EXCEPT;
+ child = content->children;
+ def->content = except;
+ if (child == NULL) {
+ xmlRngPErr(ctxt, content, XML_RNGP_EXCEPT_NO_CONTENT,
+ "except has no content\n", NULL, NULL);
+ }
+ while (child != NULL) {
+ tmp2 = xmlRelaxNGParsePattern(ctxt, child);
+ if (tmp2 != NULL) {
+ if (last == NULL) {
+ except->content = last = tmp2;
+ } else {
+ last->next = tmp2;
+ last = tmp2;
+ }
+ }
+ child = child->next;
+ }
+ content = content->next;
+ }
+ /*
+ * Check there is no unhandled data
+ */
+ if (content != NULL) {
+ xmlRngPErr(ctxt, content, XML_RNGP_DATA_CONTENT,
+ "Element data has unexpected content %s\n",
+ content->name, NULL);
+ }
+
+ return (def);
+}
+
+static const xmlChar *invalidName = BAD_CAST "\1";
+
+/**
+ * xmlRelaxNGCompareNameClasses:
+ * @defs1: the first element/attribute defs
+ * @defs2: the second element/attribute defs
+ * @name: the restriction on the name
+ * @ns: the restriction on the namespace
+ *
+ * Compare the 2 lists of element definitions. The comparison is
+ * that if both lists do not accept the same QNames, it returns 1
+ * If the 2 lists can accept the same QName the comparison returns 0
+ *
+ * Returns 1 disttinct, 0 if equal
+ */
+static int
+xmlRelaxNGCompareNameClasses(xmlRelaxNGDefinePtr def1,
+ xmlRelaxNGDefinePtr def2)
+{
+ int ret = 1;
+ xmlNode node;
+ xmlNs ns;
+ xmlRelaxNGValidCtxt ctxt;
+
+ memset(&ctxt, 0, sizeof(xmlRelaxNGValidCtxt));
+
+ ctxt.flags = FLAGS_IGNORABLE | FLAGS_NOERROR;
+
+ if ((def1->type == XML_RELAXNG_ELEMENT) ||
+ (def1->type == XML_RELAXNG_ATTRIBUTE)) {
+ if (def2->type == XML_RELAXNG_TEXT)
+ return (1);
+ if (def1->name != NULL) {
+ node.name = def1->name;
+ } else {
+ node.name = invalidName;
+ }
+ if (def1->ns != NULL) {
+ if (def1->ns[0] == 0) {
+ node.ns = NULL;
+ } else {
+ node.ns = &ns;
+ ns.href = def1->ns;
+ }
+ } else {
+ node.ns = NULL;
+ }
+ if (xmlRelaxNGElementMatch(&ctxt, def2, &node)) {
+ if (def1->nameClass != NULL) {
+ ret = xmlRelaxNGCompareNameClasses(def1->nameClass, def2);
+ } else {
+ ret = 0;
+ }
+ } else {
+ ret = 1;
+ }
+ } else if (def1->type == XML_RELAXNG_TEXT) {
+ if (def2->type == XML_RELAXNG_TEXT)
+ return (0);
+ return (1);
+ } else if (def1->type == XML_RELAXNG_EXCEPT) {
+ TODO ret = 0;
+ } else {
+ TODO ret = 0;
+ }
+ if (ret == 0)
+ return (ret);
+ if ((def2->type == XML_RELAXNG_ELEMENT) ||
+ (def2->type == XML_RELAXNG_ATTRIBUTE)) {
+ if (def2->name != NULL) {
+ node.name = def2->name;
+ } else {
+ node.name = invalidName;
+ }
+ node.ns = &ns;
+ if (def2->ns != NULL) {
+ if (def2->ns[0] == 0) {
+ node.ns = NULL;
+ } else {
+ ns.href = def2->ns;
+ }
+ } else {
+ ns.href = invalidName;
+ }
+ if (xmlRelaxNGElementMatch(&ctxt, def1, &node)) {
+ if (def2->nameClass != NULL) {
+ ret = xmlRelaxNGCompareNameClasses(def2->nameClass, def1);
+ } else {
+ ret = 0;
+ }
+ } else {
+ ret = 1;
+ }
+ } else {
+ TODO ret = 0;
+ }
+
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGCompareElemDefLists:
+ * @ctxt: a Relax-NG parser context
+ * @defs1: the first list of element/attribute defs
+ * @defs2: the second list of element/attribute defs
+ *
+ * Compare the 2 lists of element or attribute definitions. The comparison
+ * is that if both lists do not accept the same QNames, it returns 1
+ * If the 2 lists can accept the same QName the comparison returns 0
+ *
+ * Returns 1 disttinct, 0 if equal
+ */
+static int
+xmlRelaxNGCompareElemDefLists(xmlRelaxNGParserCtxtPtr ctxt
+ ATTRIBUTE_UNUSED, xmlRelaxNGDefinePtr * def1,
+ xmlRelaxNGDefinePtr * def2)
+{
+ xmlRelaxNGDefinePtr *basedef2 = def2;
+
+ if ((def1 == NULL) || (def2 == NULL))
+ return (1);
+ if ((*def1 == NULL) || (*def2 == NULL))
+ return (1);
+ while (*def1 != NULL) {
+ while ((*def2) != NULL) {
+ if (xmlRelaxNGCompareNameClasses(*def1, *def2) == 0)
+ return (0);
+ def2++;
+ }
+ def2 = basedef2;
+ def1++;
+ }
+ return (1);
+}
+
+/**
+ * xmlRelaxNGGenerateAttributes:
+ * @ctxt: a Relax-NG parser context
+ * @def: the definition definition
+ *
+ * Check if the definition can only generate attributes
+ *
+ * Returns 1 if yes, 0 if no and -1 in case of error.
+ */
+static int
+xmlRelaxNGGenerateAttributes(xmlRelaxNGParserCtxtPtr ctxt,
+ xmlRelaxNGDefinePtr def)
+{
+ xmlRelaxNGDefinePtr parent, cur, tmp;
+
+ /*
+ * Don't run that check in case of error. Infinite recursion
+ * becomes possible.
+ */
+ if (ctxt->nbErrors != 0)
+ return (-1);
+
+ parent = NULL;
+ cur = def;
+ while (cur != NULL) {
+ if ((cur->type == XML_RELAXNG_ELEMENT) ||
+ (cur->type == XML_RELAXNG_TEXT) ||
+ (cur->type == XML_RELAXNG_DATATYPE) ||
+ (cur->type == XML_RELAXNG_PARAM) ||
+ (cur->type == XML_RELAXNG_LIST) ||
+ (cur->type == XML_RELAXNG_VALUE) ||
+ (cur->type == XML_RELAXNG_EMPTY))
+ return (0);
+ if ((cur->type == XML_RELAXNG_CHOICE) ||
+ (cur->type == XML_RELAXNG_INTERLEAVE) ||
+ (cur->type == XML_RELAXNG_GROUP) ||
+ (cur->type == XML_RELAXNG_ONEORMORE) ||
+ (cur->type == XML_RELAXNG_ZEROORMORE) ||
+ (cur->type == XML_RELAXNG_OPTIONAL) ||
+ (cur->type == XML_RELAXNG_PARENTREF) ||
+ (cur->type == XML_RELAXNG_EXTERNALREF) ||
+ (cur->type == XML_RELAXNG_REF) ||
+ (cur->type == XML_RELAXNG_DEF)) {
+ if (cur->content != NULL) {
+ parent = cur;
+ cur = cur->content;
+ tmp = cur;
+ while (tmp != NULL) {
+ tmp->parent = parent;
+ tmp = tmp->next;
+ }
+ continue;
+ }
+ }
+ if (cur == def)
+ break;
+ if (cur->next != NULL) {
+ cur = cur->next;
+ continue;
+ }
+ do {
+ cur = cur->parent;
+ if (cur == NULL)
+ break;
+ if (cur == def)
+ return (1);
+ if (cur->next != NULL) {
+ cur = cur->next;
+ break;
+ }
+ } while (cur != NULL);
+ }
+ return (1);
+}
+
+/**
+ * xmlRelaxNGGetElements:
+ * @ctxt: a Relax-NG parser context
+ * @def: the definition definition
+ * @eora: gather elements (0) or attributes (1)
+ *
+ * Compute the list of top elements a definition can generate
+ *
+ * Returns a list of elements or NULL if none was found.
+ */
+static xmlRelaxNGDefinePtr *
+xmlRelaxNGGetElements(xmlRelaxNGParserCtxtPtr ctxt,
+ xmlRelaxNGDefinePtr def, int eora)
+{
+ xmlRelaxNGDefinePtr *ret = NULL, parent, cur, tmp;
+ int len = 0;
+ int max = 0;
+
+ /*
+ * Don't run that check in case of error. Infinite recursion
+ * becomes possible.
+ */
+ if (ctxt->nbErrors != 0)
+ return (NULL);
+
+ parent = NULL;
+ cur = def;
+ while (cur != NULL) {
+ if (((eora == 0) && ((cur->type == XML_RELAXNG_ELEMENT) ||
+ (cur->type == XML_RELAXNG_TEXT))) ||
+ ((eora == 1) && (cur->type == XML_RELAXNG_ATTRIBUTE))) {
+ if (ret == NULL) {
+ max = 10;
+ ret = (xmlRelaxNGDefinePtr *)
+ xmlMalloc((max + 1) * sizeof(xmlRelaxNGDefinePtr));
+ if (ret == NULL) {
+ xmlRngPErrMemory(ctxt, "getting element list\n");
+ return (NULL);
+ }
+ } else if (max <= len) {
+ xmlRelaxNGDefinePtr *temp;
+
+ max *= 2;
+ temp = xmlRealloc(ret,
+ (max + 1) * sizeof(xmlRelaxNGDefinePtr));
+ if (temp == NULL) {
+ xmlRngPErrMemory(ctxt, "getting element list\n");
+ xmlFree(ret);
+ return (NULL);
+ }
+ ret = temp;
+ }
+ ret[len++] = cur;
+ ret[len] = NULL;
+ } else if ((cur->type == XML_RELAXNG_CHOICE) ||
+ (cur->type == XML_RELAXNG_INTERLEAVE) ||
+ (cur->type == XML_RELAXNG_GROUP) ||
+ (cur->type == XML_RELAXNG_ONEORMORE) ||
+ (cur->type == XML_RELAXNG_ZEROORMORE) ||
+ (cur->type == XML_RELAXNG_OPTIONAL) ||
+ (cur->type == XML_RELAXNG_PARENTREF) ||
+ (cur->type == XML_RELAXNG_REF) ||
+ (cur->type == XML_RELAXNG_DEF) ||
+ (cur->type == XML_RELAXNG_EXTERNALREF)) {
+ /*
+ * Don't go within elements or attributes or string values.
+ * Just gather the element top list
+ */
+ if (cur->content != NULL) {
+ parent = cur;
+ cur = cur->content;
+ tmp = cur;
+ while (tmp != NULL) {
+ tmp->parent = parent;
+ tmp = tmp->next;
+ }
+ continue;
+ }
+ }
+ if (cur == def)
+ break;
+ if (cur->next != NULL) {
+ cur = cur->next;
+ continue;
+ }
+ do {
+ cur = cur->parent;
+ if (cur == NULL)
+ break;
+ if (cur == def)
+ return (ret);
+ if (cur->next != NULL) {
+ cur = cur->next;
+ break;
+ }
+ } while (cur != NULL);
+ }
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGCheckChoiceDeterminism:
+ * @ctxt: a Relax-NG parser context
+ * @def: the choice definition
+ *
+ * Also used to find indeterministic pattern in choice
+ */
+static void
+xmlRelaxNGCheckChoiceDeterminism(xmlRelaxNGParserCtxtPtr ctxt,
+ xmlRelaxNGDefinePtr def)
+{
+ xmlRelaxNGDefinePtr **list;
+ xmlRelaxNGDefinePtr cur;
+ int nbchild = 0, i, j, ret;
+ int is_nullable = 0;
+ int is_indeterminist = 0;
+ xmlHashTablePtr triage = NULL;
+ int is_triable = 1;
+
+ if ((def == NULL) || (def->type != XML_RELAXNG_CHOICE))
+ return;
+
+ if (def->dflags & IS_PROCESSED)
+ return;
+
+ /*
+ * Don't run that check in case of error. Infinite recursion
+ * becomes possible.
+ */
+ if (ctxt->nbErrors != 0)
+ return;
+
+ is_nullable = xmlRelaxNGIsNullable(def);
+
+ cur = def->content;
+ while (cur != NULL) {
+ nbchild++;
+ cur = cur->next;
+ }
+
+ list = (xmlRelaxNGDefinePtr **) xmlMalloc(nbchild *
+ sizeof(xmlRelaxNGDefinePtr
+ *));
+ if (list == NULL) {
+ xmlRngPErrMemory(ctxt, "building choice\n");
+ return;
+ }
+ i = 0;
+ /*
+ * a bit strong but safe
+ */
+ if (is_nullable == 0) {
+ triage = xmlHashCreate(10);
+ } else {
+ is_triable = 0;
+ }
+ cur = def->content;
+ while (cur != NULL) {
+ list[i] = xmlRelaxNGGetElements(ctxt, cur, 0);
+ if ((list[i] == NULL) || (list[i][0] == NULL)) {
+ is_triable = 0;
+ } else if (is_triable == 1) {
+ xmlRelaxNGDefinePtr *tmp;
+ int res;
+
+ tmp = list[i];
+ while ((*tmp != NULL) && (is_triable == 1)) {
+ if ((*tmp)->type == XML_RELAXNG_TEXT) {
+ res = xmlHashAddEntry2(triage,
+ BAD_CAST "#text", NULL,
+ (void *) cur);
+ if (res != 0)
+ is_triable = -1;
+ } else if (((*tmp)->type == XML_RELAXNG_ELEMENT) &&
+ ((*tmp)->name != NULL)) {
+ if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
+ res = xmlHashAddEntry2(triage,
+ (*tmp)->name, NULL,
+ (void *) cur);
+ else
+ res = xmlHashAddEntry2(triage,
+ (*tmp)->name, (*tmp)->ns,
+ (void *) cur);
+ if (res != 0)
+ is_triable = -1;
+ } else if ((*tmp)->type == XML_RELAXNG_ELEMENT) {
+ if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
+ res = xmlHashAddEntry2(triage,
+ BAD_CAST "#any", NULL,
+ (void *) cur);
+ else
+ res = xmlHashAddEntry2(triage,
+ BAD_CAST "#any", (*tmp)->ns,
+ (void *) cur);
+ if (res != 0)
+ is_triable = -1;
+ } else {
+ is_triable = -1;
+ }
+ tmp++;
+ }
+ }
+ i++;
+ cur = cur->next;
+ }
+
+ for (i = 0; i < nbchild; i++) {
+ if (list[i] == NULL)
+ continue;
+ for (j = 0; j < i; j++) {
+ if (list[j] == NULL)
+ continue;
+ ret = xmlRelaxNGCompareElemDefLists(ctxt, list[i], list[j]);
+ if (ret == 0) {
+ is_indeterminist = 1;
+ }
+ }
+ }
+ for (i = 0; i < nbchild; i++) {
+ if (list[i] != NULL)
+ xmlFree(list[i]);
+ }
+
+ xmlFree(list);
+ if (is_indeterminist) {
+ def->dflags |= IS_INDETERMINIST;
+ }
+ if (is_triable == 1) {
+ def->dflags |= IS_TRIABLE;
+ def->data = triage;
+ } else if (triage != NULL) {
+ xmlHashFree(triage, NULL);
+ }
+ def->dflags |= IS_PROCESSED;
+}
+
+/**
+ * xmlRelaxNGCheckGroupAttrs:
+ * @ctxt: a Relax-NG parser context
+ * @def: the group definition
+ *
+ * Detects violations of rule 7.3
+ */
+static void
+xmlRelaxNGCheckGroupAttrs(xmlRelaxNGParserCtxtPtr ctxt,
+ xmlRelaxNGDefinePtr def)
+{
+ xmlRelaxNGDefinePtr **list;
+ xmlRelaxNGDefinePtr cur;
+ int nbchild = 0, i, j, ret;
+
+ if ((def == NULL) ||
+ ((def->type != XML_RELAXNG_GROUP) &&
+ (def->type != XML_RELAXNG_ELEMENT)))
+ return;
+
+ if (def->dflags & IS_PROCESSED)
+ return;
+
+ /*
+ * Don't run that check in case of error. Infinite recursion
+ * becomes possible.
+ */
+ if (ctxt->nbErrors != 0)
+ return;
+
+ cur = def->attrs;
+ while (cur != NULL) {
+ nbchild++;
+ cur = cur->next;
+ }
+ cur = def->content;
+ while (cur != NULL) {
+ nbchild++;
+ cur = cur->next;
+ }
+
+ list = (xmlRelaxNGDefinePtr **) xmlMalloc(nbchild *
+ sizeof(xmlRelaxNGDefinePtr
+ *));
+ if (list == NULL) {
+ xmlRngPErrMemory(ctxt, "building group\n");
+ return;
+ }
+ i = 0;
+ cur = def->attrs;
+ while (cur != NULL) {
+ list[i] = xmlRelaxNGGetElements(ctxt, cur, 1);
+ i++;
+ cur = cur->next;
+ }
+ cur = def->content;
+ while (cur != NULL) {
+ list[i] = xmlRelaxNGGetElements(ctxt, cur, 1);
+ i++;
+ cur = cur->next;
+ }
+
+ for (i = 0; i < nbchild; i++) {
+ if (list[i] == NULL)
+ continue;
+ for (j = 0; j < i; j++) {
+ if (list[j] == NULL)
+ continue;
+ ret = xmlRelaxNGCompareElemDefLists(ctxt, list[i], list[j]);
+ if (ret == 0) {
+ xmlRngPErr(ctxt, def->node, XML_RNGP_GROUP_ATTR_CONFLICT,
+ "Attributes conflicts in group\n", NULL, NULL);
+ }
+ }
+ }
+ for (i = 0; i < nbchild; i++) {
+ if (list[i] != NULL)
+ xmlFree(list[i]);
+ }
+
+ xmlFree(list);
+ def->dflags |= IS_PROCESSED;
+}
+
+/**
+ * xmlRelaxNGComputeInterleaves:
+ * @def: the interleave definition
+ * @ctxt: a Relax-NG parser context
+ * @name: the definition name
+ *
+ * A lot of work for preprocessing interleave definitions
+ * is potentially needed to get a decent execution speed at runtime
+ * - trying to get a total order on the element nodes generated
+ * by the interleaves, order the list of interleave definitions
+ * following that order.
+ * - if <text/> is used to handle mixed content, it is better to
+ * flag this in the define and simplify the runtime checking
+ * algorithm
+ */
+static void
+xmlRelaxNGComputeInterleaves(xmlRelaxNGDefinePtr def,
+ xmlRelaxNGParserCtxtPtr ctxt,
+ xmlChar * name ATTRIBUTE_UNUSED)
+{
+ xmlRelaxNGDefinePtr cur, *tmp;
+
+ xmlRelaxNGPartitionPtr partitions = NULL;
+ xmlRelaxNGInterleaveGroupPtr *groups = NULL;
+ xmlRelaxNGInterleaveGroupPtr group;
+ int i, j, ret, res;
+ int nbgroups = 0;
+ int nbchild = 0;
+ int is_mixed = 0;
+ int is_determinist = 1;
+
+ /*
+ * Don't run that check in case of error. Infinite recursion
+ * becomes possible.
+ */
+ if (ctxt->nbErrors != 0)
+ return;
+
+#ifdef DEBUG_INTERLEAVE
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlRelaxNGComputeInterleaves(%s)\n", name);
+#endif
+ cur = def->content;
+ while (cur != NULL) {
+ nbchild++;
+ cur = cur->next;
+ }
+
+#ifdef DEBUG_INTERLEAVE
+ xmlGenericError(xmlGenericErrorContext, " %d child\n", nbchild);
+#endif
+ groups = (xmlRelaxNGInterleaveGroupPtr *)
+ xmlMalloc(nbchild * sizeof(xmlRelaxNGInterleaveGroupPtr));
+ if (groups == NULL)
+ goto error;
+ cur = def->content;
+ while (cur != NULL) {
+ groups[nbgroups] = (xmlRelaxNGInterleaveGroupPtr)
+ xmlMalloc(sizeof(xmlRelaxNGInterleaveGroup));
+ if (groups[nbgroups] == NULL)
+ goto error;
+ if (cur->type == XML_RELAXNG_TEXT)
+ is_mixed++;
+ groups[nbgroups]->rule = cur;
+ groups[nbgroups]->defs = xmlRelaxNGGetElements(ctxt, cur, 0);
+ groups[nbgroups]->attrs = xmlRelaxNGGetElements(ctxt, cur, 1);
+ nbgroups++;
+ cur = cur->next;
+ }
+#ifdef DEBUG_INTERLEAVE
+ xmlGenericError(xmlGenericErrorContext, " %d groups\n", nbgroups);
+#endif
+
+ /*
+ * Let's check that all rules makes a partitions according to 7.4
+ */
+ partitions = (xmlRelaxNGPartitionPtr)
+ xmlMalloc(sizeof(xmlRelaxNGPartition));
+ if (partitions == NULL)
+ goto error;
+ memset(partitions, 0, sizeof(xmlRelaxNGPartition));
+ partitions->nbgroups = nbgroups;
+ partitions->triage = xmlHashCreate(nbgroups);
+ for (i = 0; i < nbgroups; i++) {
+ group = groups[i];
+ for (j = i + 1; j < nbgroups; j++) {
+ if (groups[j] == NULL)
+ continue;
+
+ ret = xmlRelaxNGCompareElemDefLists(ctxt, group->defs,
+ groups[j]->defs);
+ if (ret == 0) {
+ xmlRngPErr(ctxt, def->node, XML_RNGP_ELEM_TEXT_CONFLICT,
+ "Element or text conflicts in interleave\n",
+ NULL, NULL);
+ }
+ ret = xmlRelaxNGCompareElemDefLists(ctxt, group->attrs,
+ groups[j]->attrs);
+ if (ret == 0) {
+ xmlRngPErr(ctxt, def->node, XML_RNGP_ATTR_CONFLICT,
+ "Attributes conflicts in interleave\n", NULL,
+ NULL);
+ }
+ }
+ tmp = group->defs;
+ if ((tmp != NULL) && (*tmp != NULL)) {
+ while (*tmp != NULL) {
+ if ((*tmp)->type == XML_RELAXNG_TEXT) {
+ res = xmlHashAddEntry2(partitions->triage,
+ BAD_CAST "#text", NULL,
+ (void *) (long) (i + 1));
+ if (res != 0)
+ is_determinist = -1;
+ } else if (((*tmp)->type == XML_RELAXNG_ELEMENT) &&
+ ((*tmp)->name != NULL)) {
+ if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
+ res = xmlHashAddEntry2(partitions->triage,
+ (*tmp)->name, NULL,
+ (void *) (long) (i + 1));
+ else
+ res = xmlHashAddEntry2(partitions->triage,
+ (*tmp)->name, (*tmp)->ns,
+ (void *) (long) (i + 1));
+ if (res != 0)
+ is_determinist = -1;
+ } else if ((*tmp)->type == XML_RELAXNG_ELEMENT) {
+ if (((*tmp)->ns == NULL) || ((*tmp)->ns[0] == 0))
+ res = xmlHashAddEntry2(partitions->triage,
+ BAD_CAST "#any", NULL,
+ (void *) (long) (i + 1));
+ else
+ res = xmlHashAddEntry2(partitions->triage,
+ BAD_CAST "#any", (*tmp)->ns,
+ (void *) (long) (i + 1));
+ if ((*tmp)->nameClass != NULL)
+ is_determinist = 2;
+ if (res != 0)
+ is_determinist = -1;
+ } else {
+ is_determinist = -1;
+ }
+ tmp++;
+ }
+ } else {
+ is_determinist = 0;
+ }
+ }
+ partitions->groups = groups;
+
+ /*
+ * and save the partition list back in the def
+ */
+ def->data = partitions;
+ if (is_mixed != 0)
+ def->dflags |= IS_MIXED;
+ if (is_determinist == 1)
+ partitions->flags = IS_DETERMINIST;
+ if (is_determinist == 2)
+ partitions->flags = IS_DETERMINIST | IS_NEEDCHECK;
+ return;
+
+ error:
+ xmlRngPErrMemory(ctxt, "in interleave computation\n");
+ if (groups != NULL) {
+ for (i = 0; i < nbgroups; i++)
+ if (groups[i] != NULL) {
+ if (groups[i]->defs != NULL)
+ xmlFree(groups[i]->defs);
+ xmlFree(groups[i]);
+ }
+ xmlFree(groups);
+ }
+ xmlRelaxNGFreePartition(partitions);
+}
+
+/**
+ * xmlRelaxNGParseInterleave:
+ * @ctxt: a Relax-NG parser context
+ * @node: the data node.
+ *
+ * parse the content of a RelaxNG interleave node.
+ *
+ * Returns the definition pointer or NULL in case of error
+ */
+static xmlRelaxNGDefinePtr
+xmlRelaxNGParseInterleave(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
+{
+ xmlRelaxNGDefinePtr def = NULL;
+ xmlRelaxNGDefinePtr last = NULL, cur;
+ xmlNodePtr child;
+
+ def = xmlRelaxNGNewDefine(ctxt, node);
+ if (def == NULL) {
+ return (NULL);
+ }
+ def->type = XML_RELAXNG_INTERLEAVE;
+
+ if (ctxt->interleaves == NULL)
+ ctxt->interleaves = xmlHashCreate(10);
+ if (ctxt->interleaves == NULL) {
+ xmlRngPErrMemory(ctxt, "create interleaves\n");
+ } else {
+ char name[32];
+
+ snprintf(name, 32, "interleave%d", ctxt->nbInterleaves++);
+ if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST name, def) < 0) {
+ xmlRngPErr(ctxt, node, XML_RNGP_INTERLEAVE_ADD,
+ "Failed to add %s to hash table\n",
+ (const xmlChar *) name, NULL);
+ }
+ }
+ child = node->children;
+ if (child == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_INTERLEAVE_NO_CONTENT,
+ "Element interleave is empty\n", NULL, NULL);
+ }
+ while (child != NULL) {
+ if (IS_RELAXNG(child, "element")) {
+ cur = xmlRelaxNGParseElement(ctxt, child);
+ } else {
+ cur = xmlRelaxNGParsePattern(ctxt, child);
+ }
+ if (cur != NULL) {
+ cur->parent = def;
+ if (last == NULL) {
+ def->content = last = cur;
+ } else {
+ last->next = cur;
+ last = cur;
+ }
+ }
+ child = child->next;
+ }
+
+ return (def);
+}
+
+/**
+ * xmlRelaxNGParseInclude:
+ * @ctxt: a Relax-NG parser context
+ * @node: the include node
+ *
+ * Integrate the content of an include node in the current grammar
+ *
+ * Returns 0 in case of success or -1 in case of error
+ */
+static int
+xmlRelaxNGParseInclude(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
+{
+ xmlRelaxNGIncludePtr incl;
+ xmlNodePtr root;
+ int ret = 0, tmp;
+
+ incl = node->psvi;
+ if (incl == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_INCLUDE_EMPTY,
+ "Include node has no data\n", NULL, NULL);
+ return (-1);
+ }
+ root = xmlDocGetRootElement(incl->doc);
+ if (root == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_EMPTY, "Include document is empty\n",
+ NULL, NULL);
+ return (-1);
+ }
+ if (!xmlStrEqual(root->name, BAD_CAST "grammar")) {
+ xmlRngPErr(ctxt, node, XML_RNGP_GRAMMAR_MISSING,
+ "Include document root is not a grammar\n", NULL, NULL);
+ return (-1);
+ }
+
+ /*
+ * Merge the definition from both the include and the internal list
+ */
+ if (root->children != NULL) {
+ tmp = xmlRelaxNGParseGrammarContent(ctxt, root->children);
+ if (tmp != 0)
+ ret = -1;
+ }
+ if (node->children != NULL) {
+ tmp = xmlRelaxNGParseGrammarContent(ctxt, node->children);
+ if (tmp != 0)
+ ret = -1;
+ }
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGParseDefine:
+ * @ctxt: a Relax-NG parser context
+ * @node: the define node
+ *
+ * parse the content of a RelaxNG define element node.
+ *
+ * Returns 0 in case of success or -1 in case of error
+ */
+static int
+xmlRelaxNGParseDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
+{
+ xmlChar *name;
+ int ret = 0, tmp;
+ xmlRelaxNGDefinePtr def;
+ const xmlChar *olddefine;
+
+ name = xmlGetProp(node, BAD_CAST "name");
+ if (name == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_NAME_MISSING,
+ "define has no name\n", NULL, NULL);
+ } else {
+ xmlRelaxNGNormExtSpace(name);
+ if (xmlValidateNCName(name, 0)) {
+ xmlRngPErr(ctxt, node, XML_RNGP_INVALID_DEFINE_NAME,
+ "define name '%s' is not an NCName\n", name, NULL);
+ }
+ def = xmlRelaxNGNewDefine(ctxt, node);
+ if (def == NULL) {
+ xmlFree(name);
+ return (-1);
+ }
+ def->type = XML_RELAXNG_DEF;
+ def->name = name;
+ if (node->children == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_EMPTY,
+ "define has no children\n", NULL, NULL);
+ } else {
+ olddefine = ctxt->define;
+ ctxt->define = name;
+ def->content =
+ xmlRelaxNGParsePatterns(ctxt, node->children, 0);
+ ctxt->define = olddefine;
+ }
+ if (ctxt->grammar->defs == NULL)
+ ctxt->grammar->defs = xmlHashCreate(10);
+ if (ctxt->grammar->defs == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_CREATE_FAILED,
+ "Could not create definition hash\n", NULL, NULL);
+ ret = -1;
+ } else {
+ tmp = xmlHashAddEntry(ctxt->grammar->defs, name, def);
+ if (tmp < 0) {
+ xmlRelaxNGDefinePtr prev;
+
+ prev = xmlHashLookup(ctxt->grammar->defs, name);
+ if (prev == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_DEFINE_CREATE_FAILED,
+ "Internal error on define aggregation of %s\n",
+ name, NULL);
+ ret = -1;
+ } else {
+ while (prev->nextHash != NULL)
+ prev = prev->nextHash;
+ prev->nextHash = def;
+ }
+ }
+ }
+ }
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGProcessExternalRef:
+ * @ctxt: the parser context
+ * @node: the externlRef node
+ *
+ * Process and compile an externlRef node
+ *
+ * Returns the xmlRelaxNGDefinePtr or NULL in case of error
+ */
+static xmlRelaxNGDefinePtr
+xmlRelaxNGProcessExternalRef(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
+{
+ xmlRelaxNGDocumentPtr docu;
+ xmlNodePtr root, tmp;
+ xmlChar *ns;
+ int newNs = 0, oldflags;
+ xmlRelaxNGDefinePtr def;
+
+ docu = node->psvi;
+ if (docu != NULL) {
+ def = xmlRelaxNGNewDefine(ctxt, node);
+ if (def == NULL)
+ return (NULL);
+ def->type = XML_RELAXNG_EXTERNALREF;
+
+ if (docu->content == NULL) {
+ /*
+ * Then do the parsing for good
+ */
+ root = xmlDocGetRootElement(docu->doc);
+ if (root == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_EXTERNALREF_EMTPY,
+ "xmlRelaxNGParse: %s is empty\n", ctxt->URL,
+ NULL);
+ return (NULL);
+ }
+ /*
+ * ns transmission rules
+ */
+ ns = xmlGetProp(root, BAD_CAST "ns");
+ if (ns == NULL) {
+ tmp = node;
+ while ((tmp != NULL) && (tmp->type == XML_ELEMENT_NODE)) {
+ ns = xmlGetProp(tmp, BAD_CAST "ns");
+ if (ns != NULL) {
+ break;
+ }
+ tmp = tmp->parent;
+ }
+ if (ns != NULL) {
+ xmlSetProp(root, BAD_CAST "ns", ns);
+ newNs = 1;
+ xmlFree(ns);
+ }
+ } else {
+ xmlFree(ns);
+ }
+
+ /*
+ * Parsing to get a precompiled schemas.
+ */
+ oldflags = ctxt->flags;
+ ctxt->flags |= XML_RELAXNG_IN_EXTERNALREF;
+ docu->schema = xmlRelaxNGParseDocument(ctxt, root);
+ ctxt->flags = oldflags;
+ if ((docu->schema != NULL) &&
+ (docu->schema->topgrammar != NULL)) {
+ docu->content = docu->schema->topgrammar->start;
+ }
+
+ /*
+ * the externalRef may be reused in a different ns context
+ */
+ if (newNs == 1) {
+ xmlUnsetProp(root, BAD_CAST "ns");
+ }
+ }
+ def->content = docu->content;
+ } else {
+ def = NULL;
+ }
+ return (def);
+}
+
+/**
+ * xmlRelaxNGParsePattern:
+ * @ctxt: a Relax-NG parser context
+ * @node: the pattern node.
+ *
+ * parse the content of a RelaxNG pattern node.
+ *
+ * Returns the definition pointer or NULL in case of error or if no
+ * pattern is generated.
+ */
+static xmlRelaxNGDefinePtr
+xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
+{
+ xmlRelaxNGDefinePtr def = NULL;
+
+ if (node == NULL) {
+ return (NULL);
+ }
+ if (IS_RELAXNG(node, "element")) {
+ def = xmlRelaxNGParseElement(ctxt, node);
+ } else if (IS_RELAXNG(node, "attribute")) {
+ def = xmlRelaxNGParseAttribute(ctxt, node);
+ } else if (IS_RELAXNG(node, "empty")) {
+ def = xmlRelaxNGNewDefine(ctxt, node);
+ if (def == NULL)
+ return (NULL);
+ def->type = XML_RELAXNG_EMPTY;
+ if (node->children != NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_NOT_EMPTY,
+ "empty: had a child node\n", NULL, NULL);
+ }
+ } else if (IS_RELAXNG(node, "text")) {
+ def = xmlRelaxNGNewDefine(ctxt, node);
+ if (def == NULL)
+ return (NULL);
+ def->type = XML_RELAXNG_TEXT;
+ if (node->children != NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_TEXT_HAS_CHILD,
+ "text: had a child node\n", NULL, NULL);
+ }
+ } else if (IS_RELAXNG(node, "zeroOrMore")) {
+ def = xmlRelaxNGNewDefine(ctxt, node);
+ if (def == NULL)
+ return (NULL);
+ def->type = XML_RELAXNG_ZEROORMORE;
+ if (node->children == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
+ "Element %s is empty\n", node->name, NULL);
+ } else {
+ def->content =
+ xmlRelaxNGParsePatterns(ctxt, node->children, 1);
+ }
+ } else if (IS_RELAXNG(node, "oneOrMore")) {
+ def = xmlRelaxNGNewDefine(ctxt, node);
+ if (def == NULL)
+ return (NULL);
+ def->type = XML_RELAXNG_ONEORMORE;
+ if (node->children == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
+ "Element %s is empty\n", node->name, NULL);
+ } else {
+ def->content =
+ xmlRelaxNGParsePatterns(ctxt, node->children, 1);
+ }
+ } else if (IS_RELAXNG(node, "optional")) {
+ def = xmlRelaxNGNewDefine(ctxt, node);
+ if (def == NULL)
+ return (NULL);
+ def->type = XML_RELAXNG_OPTIONAL;
+ if (node->children == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
+ "Element %s is empty\n", node->name, NULL);
+ } else {
+ def->content =
+ xmlRelaxNGParsePatterns(ctxt, node->children, 1);
+ }
+ } else if (IS_RELAXNG(node, "choice")) {
+ def = xmlRelaxNGNewDefine(ctxt, node);
+ if (def == NULL)
+ return (NULL);
+ def->type = XML_RELAXNG_CHOICE;
+ if (node->children == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
+ "Element %s is empty\n", node->name, NULL);
+ } else {
+ def->content =
+ xmlRelaxNGParsePatterns(ctxt, node->children, 0);
+ }
+ } else if (IS_RELAXNG(node, "group")) {
+ def = xmlRelaxNGNewDefine(ctxt, node);
+ if (def == NULL)
+ return (NULL);
+ def->type = XML_RELAXNG_GROUP;
+ if (node->children == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
+ "Element %s is empty\n", node->name, NULL);
+ } else {
+ def->content =
+ xmlRelaxNGParsePatterns(ctxt, node->children, 0);
+ }
+ } else if (IS_RELAXNG(node, "ref")) {
+ def = xmlRelaxNGNewDefine(ctxt, node);
+ if (def == NULL)
+ return (NULL);
+ def->type = XML_RELAXNG_REF;
+ def->name = xmlGetProp(node, BAD_CAST "name");
+ if (def->name == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_REF_NO_NAME, "ref has no name\n",
+ NULL, NULL);
+ } else {
+ xmlRelaxNGNormExtSpace(def->name);
+ if (xmlValidateNCName(def->name, 0)) {
+ xmlRngPErr(ctxt, node, XML_RNGP_REF_NAME_INVALID,
+ "ref name '%s' is not an NCName\n", def->name,
+ NULL);
+ }
+ }
+ if (node->children != NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_REF_NOT_EMPTY, "ref is not empty\n",
+ NULL, NULL);
+ }
+ if (ctxt->grammar->refs == NULL)
+ ctxt->grammar->refs = xmlHashCreate(10);
+ if (ctxt->grammar->refs == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_REF_CREATE_FAILED,
+ "Could not create references hash\n", NULL, NULL);
+ def = NULL;
+ } else {
+ int tmp;
+
+ tmp = xmlHashAddEntry(ctxt->grammar->refs, def->name, def);
+ if (tmp < 0) {
+ xmlRelaxNGDefinePtr prev;
+
+ prev = (xmlRelaxNGDefinePtr)
+ xmlHashLookup(ctxt->grammar->refs, def->name);
+ if (prev == NULL) {
+ if (def->name != NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_REF_CREATE_FAILED,
+ "Error refs definitions '%s'\n",
+ def->name, NULL);
+ } else {
+ xmlRngPErr(ctxt, node, XML_RNGP_REF_CREATE_FAILED,
+ "Error refs definitions\n",
+ NULL, NULL);
+ }
+ def = NULL;
+ } else {
+ def->nextHash = prev->nextHash;
+ prev->nextHash = def;
+ }
+ }
+ }
+ } else if (IS_RELAXNG(node, "data")) {
+ def = xmlRelaxNGParseData(ctxt, node);
+ } else if (IS_RELAXNG(node, "value")) {
+ def = xmlRelaxNGParseValue(ctxt, node);
+ } else if (IS_RELAXNG(node, "list")) {
+ def = xmlRelaxNGNewDefine(ctxt, node);
+ if (def == NULL)
+ return (NULL);
+ def->type = XML_RELAXNG_LIST;
+ if (node->children == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT,
+ "Element %s is empty\n", node->name, NULL);
+ } else {
+ def->content =
+ xmlRelaxNGParsePatterns(ctxt, node->children, 0);
+ }
+ } else if (IS_RELAXNG(node, "interleave")) {
+ def = xmlRelaxNGParseInterleave(ctxt, node);
+ } else if (IS_RELAXNG(node, "externalRef")) {
+ def = xmlRelaxNGProcessExternalRef(ctxt, node);
+ } else if (IS_RELAXNG(node, "notAllowed")) {
+ def = xmlRelaxNGNewDefine(ctxt, node);
+ if (def == NULL)
+ return (NULL);
+ def->type = XML_RELAXNG_NOT_ALLOWED;
+ if (node->children != NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_NOTALLOWED_NOT_EMPTY,
+ "xmlRelaxNGParse: notAllowed element is not empty\n",
+ NULL, NULL);
+ }
+ } else if (IS_RELAXNG(node, "grammar")) {
+ xmlRelaxNGGrammarPtr grammar, old;
+ xmlRelaxNGGrammarPtr oldparent;
+
+#ifdef DEBUG_GRAMMAR
+ xmlGenericError(xmlGenericErrorContext,
+ "Found <grammar> pattern\n");
+#endif
+
+ oldparent = ctxt->parentgrammar;
+ old = ctxt->grammar;
+ ctxt->parentgrammar = old;
+ grammar = xmlRelaxNGParseGrammar(ctxt, node->children);
+ if (old != NULL) {
+ ctxt->grammar = old;
+ ctxt->parentgrammar = oldparent;
+#if 0
+ if (grammar != NULL) {
+ grammar->next = old->next;
+ old->next = grammar;
+ }
+#endif
+ }
+ if (grammar != NULL)
+ def = grammar->start;
+ else
+ def = NULL;
+ } else if (IS_RELAXNG(node, "parentRef")) {
+ if (ctxt->parentgrammar == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NO_PARENT,
+ "Use of parentRef without a parent grammar\n", NULL,
+ NULL);
+ return (NULL);
+ }
+ def = xmlRelaxNGNewDefine(ctxt, node);
+ if (def == NULL)
+ return (NULL);
+ def->type = XML_RELAXNG_PARENTREF;
+ def->name = xmlGetProp(node, BAD_CAST "name");
+ if (def->name == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NO_NAME,
+ "parentRef has no name\n", NULL, NULL);
+ } else {
+ xmlRelaxNGNormExtSpace(def->name);
+ if (xmlValidateNCName(def->name, 0)) {
+ xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NAME_INVALID,
+ "parentRef name '%s' is not an NCName\n",
+ def->name, NULL);
+ }
+ }
+ if (node->children != NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_NOT_EMPTY,
+ "parentRef is not empty\n", NULL, NULL);
+ }
+ if (ctxt->parentgrammar->refs == NULL)
+ ctxt->parentgrammar->refs = xmlHashCreate(10);
+ if (ctxt->parentgrammar->refs == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_CREATE_FAILED,
+ "Could not create references hash\n", NULL, NULL);
+ def = NULL;
+ } else if (def->name != NULL) {
+ int tmp;
+
+ tmp =
+ xmlHashAddEntry(ctxt->parentgrammar->refs, def->name, def);
+ if (tmp < 0) {
+ xmlRelaxNGDefinePtr prev;
+
+ prev = (xmlRelaxNGDefinePtr)
+ xmlHashLookup(ctxt->parentgrammar->refs, def->name);
+ if (prev == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_PARENTREF_CREATE_FAILED,
+ "Internal error parentRef definitions '%s'\n",
+ def->name, NULL);
+ def = NULL;
+ } else {
+ def->nextHash = prev->nextHash;
+ prev->nextHash = def;
+ }
+ }
+ }
+ } else if (IS_RELAXNG(node, "mixed")) {
+ if (node->children == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_EMPTY_CONSTRUCT, "Mixed is empty\n",
+ NULL, NULL);
+ def = NULL;
+ } else {
+ def = xmlRelaxNGParseInterleave(ctxt, node);
+ if (def != NULL) {
+ xmlRelaxNGDefinePtr tmp;
+
+ if ((def->content != NULL) && (def->content->next != NULL)) {
+ tmp = xmlRelaxNGNewDefine(ctxt, node);
+ if (tmp != NULL) {
+ tmp->type = XML_RELAXNG_GROUP;
+ tmp->content = def->content;
+ def->content = tmp;
+ }
+ }
+
+ tmp = xmlRelaxNGNewDefine(ctxt, node);
+ if (tmp == NULL)
+ return (def);
+ tmp->type = XML_RELAXNG_TEXT;
+ tmp->next = def->content;
+ def->content = tmp;
+ }
+ }
+ } else {
+ xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_CONSTRUCT,
+ "Unexpected node %s is not a pattern\n", node->name,
+ NULL);
+ def = NULL;
+ }
+ return (def);
+}
+
+/**
+ * xmlRelaxNGParseAttribute:
+ * @ctxt: a Relax-NG parser context
+ * @node: the element node
+ *
+ * parse the content of a RelaxNG attribute node.
+ *
+ * Returns the definition pointer or NULL in case of error.
+ */
+static xmlRelaxNGDefinePtr
+xmlRelaxNGParseAttribute(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
+{
+ xmlRelaxNGDefinePtr ret, cur;
+ xmlNodePtr child;
+ int old_flags;
+
+ ret = xmlRelaxNGNewDefine(ctxt, node);
+ if (ret == NULL)
+ return (NULL);
+ ret->type = XML_RELAXNG_ATTRIBUTE;
+ ret->parent = ctxt->def;
+ child = node->children;
+ if (child == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_EMPTY,
+ "xmlRelaxNGParseattribute: attribute has no children\n",
+ NULL, NULL);
+ return (ret);
+ }
+ old_flags = ctxt->flags;
+ ctxt->flags |= XML_RELAXNG_IN_ATTRIBUTE;
+ cur = xmlRelaxNGParseNameClass(ctxt, child, ret);
+ if (cur != NULL)
+ child = child->next;
+
+ if (child != NULL) {
+ cur = xmlRelaxNGParsePattern(ctxt, child);
+ if (cur != NULL) {
+ switch (cur->type) {
+ case XML_RELAXNG_EMPTY:
+ case XML_RELAXNG_NOT_ALLOWED:
+ case XML_RELAXNG_TEXT:
+ case XML_RELAXNG_ELEMENT:
+ case XML_RELAXNG_DATATYPE:
+ case XML_RELAXNG_VALUE:
+ case XML_RELAXNG_LIST:
+ case XML_RELAXNG_REF:
+ case XML_RELAXNG_PARENTREF:
+ case XML_RELAXNG_EXTERNALREF:
+ case XML_RELAXNG_DEF:
+ case XML_RELAXNG_ONEORMORE:
+ case XML_RELAXNG_ZEROORMORE:
+ case XML_RELAXNG_OPTIONAL:
+ case XML_RELAXNG_CHOICE:
+ case XML_RELAXNG_GROUP:
+ case XML_RELAXNG_INTERLEAVE:
+ case XML_RELAXNG_ATTRIBUTE:
+ ret->content = cur;
+ cur->parent = ret;
+ break;
+ case XML_RELAXNG_START:
+ case XML_RELAXNG_PARAM:
+ case XML_RELAXNG_EXCEPT:
+ xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_CONTENT,
+ "attribute has invalid content\n", NULL,
+ NULL);
+ break;
+ case XML_RELAXNG_NOOP:
+ xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_NOOP,
+ "RNG Internal error, noop found in attribute\n",
+ NULL, NULL);
+ break;
+ }
+ }
+ child = child->next;
+ }
+ if (child != NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_ATTRIBUTE_CHILDREN,
+ "attribute has multiple children\n", NULL, NULL);
+ }
+ ctxt->flags = old_flags;
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGParseExceptNameClass:
+ * @ctxt: a Relax-NG parser context
+ * @node: the except node
+ * @attr: 1 if within an attribute, 0 if within an element
+ *
+ * parse the content of a RelaxNG nameClass node.
+ *
+ * Returns the definition pointer or NULL in case of error.
+ */
+static xmlRelaxNGDefinePtr
+xmlRelaxNGParseExceptNameClass(xmlRelaxNGParserCtxtPtr ctxt,
+ xmlNodePtr node, int attr)
+{
+ xmlRelaxNGDefinePtr ret, cur, last = NULL;
+ xmlNodePtr child;
+
+ if (!IS_RELAXNG(node, "except")) {
+ xmlRngPErr(ctxt, node, XML_RNGP_EXCEPT_MISSING,
+ "Expecting an except node\n", NULL, NULL);
+ return (NULL);
+ }
+ if (node->next != NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_EXCEPT_MULTIPLE,
+ "exceptNameClass allows only a single except node\n",
+ NULL, NULL);
+ }
+ if (node->children == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_EXCEPT_EMPTY, "except has no content\n",
+ NULL, NULL);
+ return (NULL);
+ }
+
+ ret = xmlRelaxNGNewDefine(ctxt, node);
+ if (ret == NULL)
+ return (NULL);
+ ret->type = XML_RELAXNG_EXCEPT;
+ child = node->children;
+ while (child != NULL) {
+ cur = xmlRelaxNGNewDefine(ctxt, child);
+ if (cur == NULL)
+ break;
+ if (attr)
+ cur->type = XML_RELAXNG_ATTRIBUTE;
+ else
+ cur->type = XML_RELAXNG_ELEMENT;
+
+ if (xmlRelaxNGParseNameClass(ctxt, child, cur) != NULL) {
+ if (last == NULL) {
+ ret->content = cur;
+ } else {
+ last->next = cur;
+ }
+ last = cur;
+ }
+ child = child->next;
+ }
+
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGParseNameClass:
+ * @ctxt: a Relax-NG parser context
+ * @node: the nameClass node
+ * @def: the current definition
+ *
+ * parse the content of a RelaxNG nameClass node.
+ *
+ * Returns the definition pointer or NULL in case of error.
+ */
+static xmlRelaxNGDefinePtr
+xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node,
+ xmlRelaxNGDefinePtr def)
+{
+ xmlRelaxNGDefinePtr ret, tmp;
+ xmlChar *val;
+
+ ret = def;
+ if ((IS_RELAXNG(node, "name")) || (IS_RELAXNG(node, "anyName")) ||
+ (IS_RELAXNG(node, "nsName"))) {
+ if ((def->type != XML_RELAXNG_ELEMENT) &&
+ (def->type != XML_RELAXNG_ATTRIBUTE)) {
+ ret = xmlRelaxNGNewDefine(ctxt, node);
+ if (ret == NULL)
+ return (NULL);
+ ret->parent = def;
+ if (ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE)
+ ret->type = XML_RELAXNG_ATTRIBUTE;
+ else
+ ret->type = XML_RELAXNG_ELEMENT;
+ }
+ }
+ if (IS_RELAXNG(node, "name")) {
+ val = xmlNodeGetContent(node);
+ xmlRelaxNGNormExtSpace(val);
+ if (xmlValidateNCName(val, 0)) {
+ if (node->parent != NULL)
+ xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_NAME,
+ "Element %s name '%s' is not an NCName\n",
+ node->parent->name, val);
+ else
+ xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_NAME,
+ "name '%s' is not an NCName\n",
+ val, NULL);
+ }
+ ret->name = val;
+ val = xmlGetProp(node, BAD_CAST "ns");
+ ret->ns = val;
+ if ((ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) &&
+ (val != NULL) &&
+ (xmlStrEqual(val, BAD_CAST "http://www.w3.org/2000/xmlns"))) {
+ xmlRngPErr(ctxt, node, XML_RNGP_XML_NS,
+ "Attribute with namespace '%s' is not allowed\n",
+ val, NULL);
+ }
+ if ((ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) &&
+ (val != NULL) &&
+ (val[0] == 0) && (xmlStrEqual(ret->name, BAD_CAST "xmlns"))) {
+ xmlRngPErr(ctxt, node, XML_RNGP_XMLNS_NAME,
+ "Attribute with QName 'xmlns' is not allowed\n",
+ val, NULL);
+ }
+ } else if (IS_RELAXNG(node, "anyName")) {
+ ret->name = NULL;
+ ret->ns = NULL;
+ if (node->children != NULL) {
+ ret->nameClass =
+ xmlRelaxNGParseExceptNameClass(ctxt, node->children,
+ (def->type ==
+ XML_RELAXNG_ATTRIBUTE));
+ }
+ } else if (IS_RELAXNG(node, "nsName")) {
+ ret->name = NULL;
+ ret->ns = xmlGetProp(node, BAD_CAST "ns");
+ if (ret->ns == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_NSNAME_NO_NS,
+ "nsName has no ns attribute\n", NULL, NULL);
+ }
+ if ((ctxt->flags & XML_RELAXNG_IN_ATTRIBUTE) &&
+ (ret->ns != NULL) &&
+ (xmlStrEqual
+ (ret->ns, BAD_CAST "http://www.w3.org/2000/xmlns"))) {
+ xmlRngPErr(ctxt, node, XML_RNGP_XML_NS,
+ "Attribute with namespace '%s' is not allowed\n",
+ ret->ns, NULL);
+ }
+ if (node->children != NULL) {
+ ret->nameClass =
+ xmlRelaxNGParseExceptNameClass(ctxt, node->children,
+ (def->type ==
+ XML_RELAXNG_ATTRIBUTE));
+ }
+ } else if (IS_RELAXNG(node, "choice")) {
+ xmlNodePtr child;
+ xmlRelaxNGDefinePtr last = NULL;
+
+ ret = xmlRelaxNGNewDefine(ctxt, node);
+ if (ret == NULL)
+ return (NULL);
+ ret->parent = def;
+ ret->type = XML_RELAXNG_CHOICE;
+
+ if (node->children == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_CHOICE_EMPTY,
+ "Element choice is empty\n", NULL, NULL);
+ } else {
+
+ child = node->children;
+ while (child != NULL) {
+ tmp = xmlRelaxNGParseNameClass(ctxt, child, ret);
+ if (tmp != NULL) {
+ if (last == NULL) {
+ last = ret->nameClass = tmp;
+ } else {
+ last->next = tmp;
+ last = tmp;
+ }
+ }
+ child = child->next;
+ }
+ }
+ } else {
+ xmlRngPErr(ctxt, node, XML_RNGP_CHOICE_CONTENT,
+ "expecting name, anyName, nsName or choice : got %s\n",
+ node->name, NULL);
+ return (NULL);
+ }
+ if (ret != def) {
+ if (def->nameClass == NULL) {
+ def->nameClass = ret;
+ } else {
+ tmp = def->nameClass;
+ while (tmp->next != NULL) {
+ tmp = tmp->next;
+ }
+ tmp->next = ret;
+ }
+ }
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGParseElement:
+ * @ctxt: a Relax-NG parser context
+ * @node: the element node
+ *
+ * parse the content of a RelaxNG element node.
+ *
+ * Returns the definition pointer or NULL in case of error.
+ */
+static xmlRelaxNGDefinePtr
+xmlRelaxNGParseElement(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
+{
+ xmlRelaxNGDefinePtr ret, cur, last;
+ xmlNodePtr child;
+ const xmlChar *olddefine;
+
+ ret = xmlRelaxNGNewDefine(ctxt, node);
+ if (ret == NULL)
+ return (NULL);
+ ret->type = XML_RELAXNG_ELEMENT;
+ ret->parent = ctxt->def;
+ child = node->children;
+ if (child == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_EMPTY,
+ "xmlRelaxNGParseElement: element has no children\n",
+ NULL, NULL);
+ return (ret);
+ }
+ cur = xmlRelaxNGParseNameClass(ctxt, child, ret);
+ if (cur != NULL)
+ child = child->next;
+
+ if (child == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_NO_CONTENT,
+ "xmlRelaxNGParseElement: element has no content\n",
+ NULL, NULL);
+ return (ret);
+ }
+ olddefine = ctxt->define;
+ ctxt->define = NULL;
+ last = NULL;
+ while (child != NULL) {
+ cur = xmlRelaxNGParsePattern(ctxt, child);
+ if (cur != NULL) {
+ cur->parent = ret;
+ switch (cur->type) {
+ case XML_RELAXNG_EMPTY:
+ case XML_RELAXNG_NOT_ALLOWED:
+ case XML_RELAXNG_TEXT:
+ case XML_RELAXNG_ELEMENT:
+ case XML_RELAXNG_DATATYPE:
+ case XML_RELAXNG_VALUE:
+ case XML_RELAXNG_LIST:
+ case XML_RELAXNG_REF:
+ case XML_RELAXNG_PARENTREF:
+ case XML_RELAXNG_EXTERNALREF:
+ case XML_RELAXNG_DEF:
+ case XML_RELAXNG_ZEROORMORE:
+ case XML_RELAXNG_ONEORMORE:
+ case XML_RELAXNG_OPTIONAL:
+ case XML_RELAXNG_CHOICE:
+ case XML_RELAXNG_GROUP:
+ case XML_RELAXNG_INTERLEAVE:
+ if (last == NULL) {
+ ret->content = last = cur;
+ } else {
+ if ((last->type == XML_RELAXNG_ELEMENT) &&
+ (ret->content == last)) {
+ ret->content = xmlRelaxNGNewDefine(ctxt, node);
+ if (ret->content != NULL) {
+ ret->content->type = XML_RELAXNG_GROUP;
+ ret->content->content = last;
+ } else {
+ ret->content = last;
+ }
+ }
+ last->next = cur;
+ last = cur;
+ }
+ break;
+ case XML_RELAXNG_ATTRIBUTE:
+ cur->next = ret->attrs;
+ ret->attrs = cur;
+ break;
+ case XML_RELAXNG_START:
+ xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,
+ "RNG Internal error, start found in element\n",
+ NULL, NULL);
+ break;
+ case XML_RELAXNG_PARAM:
+ xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,
+ "RNG Internal error, param found in element\n",
+ NULL, NULL);
+ break;
+ case XML_RELAXNG_EXCEPT:
+ xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,
+ "RNG Internal error, except found in element\n",
+ NULL, NULL);
+ break;
+ case XML_RELAXNG_NOOP:
+ xmlRngPErr(ctxt, node, XML_RNGP_ELEMENT_CONTENT,
+ "RNG Internal error, noop found in element\n",
+ NULL, NULL);
+ break;
+ }
+ }
+ child = child->next;
+ }
+ ctxt->define = olddefine;
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGParsePatterns:
+ * @ctxt: a Relax-NG parser context
+ * @nodes: list of nodes
+ * @group: use an implicit <group> for elements
+ *
+ * parse the content of a RelaxNG start node.
+ *
+ * Returns the definition pointer or NULL in case of error.
+ */
+static xmlRelaxNGDefinePtr
+xmlRelaxNGParsePatterns(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes,
+ int group)
+{
+ xmlRelaxNGDefinePtr def = NULL, last = NULL, cur, parent;
+
+ parent = ctxt->def;
+ while (nodes != NULL) {
+ if (IS_RELAXNG(nodes, "element")) {
+ cur = xmlRelaxNGParseElement(ctxt, nodes);
+ if (def == NULL) {
+ def = last = cur;
+ } else {
+ if ((group == 1) && (def->type == XML_RELAXNG_ELEMENT) &&
+ (def == last)) {
+ def = xmlRelaxNGNewDefine(ctxt, nodes);
+ def->type = XML_RELAXNG_GROUP;
+ def->content = last;
+ }
+ last->next = cur;
+ last = cur;
+ }
+ cur->parent = parent;
+ } else {
+ cur = xmlRelaxNGParsePattern(ctxt, nodes);
+ if (cur != NULL) {
+ if (def == NULL) {
+ def = last = cur;
+ } else {
+ last->next = cur;
+ last = cur;
+ }
+ }
+ }
+ nodes = nodes->next;
+ }
+ return (def);
+}
+
+/**
+ * xmlRelaxNGParseStart:
+ * @ctxt: a Relax-NG parser context
+ * @nodes: start children nodes
+ *
+ * parse the content of a RelaxNG start node.
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+static int
+xmlRelaxNGParseStart(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes)
+{
+ int ret = 0;
+ xmlRelaxNGDefinePtr def = NULL, last;
+
+ if (nodes == NULL) {
+ xmlRngPErr(ctxt, nodes, XML_RNGP_START_EMPTY, "start has no children\n",
+ NULL, NULL);
+ return (-1);
+ }
+ if (IS_RELAXNG(nodes, "empty")) {
+ def = xmlRelaxNGNewDefine(ctxt, nodes);
+ if (def == NULL)
+ return (-1);
+ def->type = XML_RELAXNG_EMPTY;
+ if (nodes->children != NULL) {
+ xmlRngPErr(ctxt, nodes, XML_RNGP_EMPTY_CONTENT,
+ "element empty is not empty\n", NULL, NULL);
+ }
+ } else if (IS_RELAXNG(nodes, "notAllowed")) {
+ def = xmlRelaxNGNewDefine(ctxt, nodes);
+ if (def == NULL)
+ return (-1);
+ def->type = XML_RELAXNG_NOT_ALLOWED;
+ if (nodes->children != NULL) {
+ xmlRngPErr(ctxt, nodes, XML_RNGP_NOTALLOWED_NOT_EMPTY,
+ "element notAllowed is not empty\n", NULL, NULL);
+ }
+ } else {
+ def = xmlRelaxNGParsePatterns(ctxt, nodes, 1);
+ }
+ if (ctxt->grammar->start != NULL) {
+ last = ctxt->grammar->start;
+ while (last->next != NULL)
+ last = last->next;
+ last->next = def;
+ } else {
+ ctxt->grammar->start = def;
+ }
+ nodes = nodes->next;
+ if (nodes != NULL) {
+ xmlRngPErr(ctxt, nodes, XML_RNGP_START_CONTENT,
+ "start more than one children\n", NULL, NULL);
+ return (-1);
+ }
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGParseGrammarContent:
+ * @ctxt: a Relax-NG parser context
+ * @nodes: grammar children nodes
+ *
+ * parse the content of a RelaxNG grammar node.
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+static int
+xmlRelaxNGParseGrammarContent(xmlRelaxNGParserCtxtPtr ctxt,
+ xmlNodePtr nodes)
+{
+ int ret = 0, tmp;
+
+ if (nodes == NULL) {
+ xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_EMPTY,
+ "grammar has no children\n", NULL, NULL);
+ return (-1);
+ }
+ while (nodes != NULL) {
+ if (IS_RELAXNG(nodes, "start")) {
+ if (nodes->children == NULL) {
+ xmlRngPErr(ctxt, nodes, XML_RNGP_START_EMPTY,
+ "start has no children\n", NULL, NULL);
+ } else {
+ tmp = xmlRelaxNGParseStart(ctxt, nodes->children);
+ if (tmp != 0)
+ ret = -1;
+ }
+ } else if (IS_RELAXNG(nodes, "define")) {
+ tmp = xmlRelaxNGParseDefine(ctxt, nodes);
+ if (tmp != 0)
+ ret = -1;
+ } else if (IS_RELAXNG(nodes, "include")) {
+ tmp = xmlRelaxNGParseInclude(ctxt, nodes);
+ if (tmp != 0)
+ ret = -1;
+ } else {
+ xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_CONTENT,
+ "grammar has unexpected child %s\n", nodes->name,
+ NULL);
+ ret = -1;
+ }
+ nodes = nodes->next;
+ }
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGCheckReference:
+ * @ref: the ref
+ * @ctxt: a Relax-NG parser context
+ * @name: the name associated to the defines
+ *
+ * Applies the 4.17. combine attribute rule for all the define
+ * element of a given grammar using the same name.
+ */
+static void
+xmlRelaxNGCheckReference(xmlRelaxNGDefinePtr ref,
+ xmlRelaxNGParserCtxtPtr ctxt,
+ const xmlChar * name)
+{
+ xmlRelaxNGGrammarPtr grammar;
+ xmlRelaxNGDefinePtr def, cur;
+
+ grammar = ctxt->grammar;
+ if (grammar == NULL) {
+ xmlRngPErr(ctxt, ref->node, XML_ERR_INTERNAL_ERROR,
+ "Internal error: no grammar in CheckReference %s\n",
+ name, NULL);
+ return;
+ }
+ if (ref->content != NULL) {
+ xmlRngPErr(ctxt, ref->node, XML_ERR_INTERNAL_ERROR,
+ "Internal error: reference has content in CheckReference %s\n",
+ name, NULL);
+ return;
+ }
+ if (grammar->defs != NULL) {
+ def = xmlHashLookup(grammar->defs, name);
+ if (def != NULL) {
+ cur = ref;
+ while (cur != NULL) {
+ cur->content = def;
+ cur = cur->nextHash;
+ }
+ } else {
+ xmlRngPErr(ctxt, ref->node, XML_RNGP_REF_NO_DEF,
+ "Reference %s has no matching definition\n", name,
+ NULL);
+ }
+ } else {
+ xmlRngPErr(ctxt, ref->node, XML_RNGP_REF_NO_DEF,
+ "Reference %s has no matching definition\n", name,
+ NULL);
+ }
+}
+
+/**
+ * xmlRelaxNGCheckCombine:
+ * @define: the define(s) list
+ * @ctxt: a Relax-NG parser context
+ * @name: the name associated to the defines
+ *
+ * Applies the 4.17. combine attribute rule for all the define
+ * element of a given grammar using the same name.
+ */
+static void
+xmlRelaxNGCheckCombine(xmlRelaxNGDefinePtr define,
+ xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * name)
+{
+ xmlChar *combine;
+ int choiceOrInterleave = -1;
+ int missing = 0;
+ xmlRelaxNGDefinePtr cur, last, tmp, tmp2;
+
+ if (define->nextHash == NULL)
+ return;
+ cur = define;
+ while (cur != NULL) {
+ combine = xmlGetProp(cur->node, BAD_CAST "combine");
+ if (combine != NULL) {
+ if (xmlStrEqual(combine, BAD_CAST "choice")) {
+ if (choiceOrInterleave == -1)
+ choiceOrInterleave = 1;
+ else if (choiceOrInterleave == 0) {
+ xmlRngPErr(ctxt, define->node, XML_RNGP_DEF_CHOICE_AND_INTERLEAVE,
+ "Defines for %s use both 'choice' and 'interleave'\n",
+ name, NULL);
+ }
+ } else if (xmlStrEqual(combine, BAD_CAST "interleave")) {
+ if (choiceOrInterleave == -1)
+ choiceOrInterleave = 0;
+ else if (choiceOrInterleave == 1) {
+ xmlRngPErr(ctxt, define->node, XML_RNGP_DEF_CHOICE_AND_INTERLEAVE,
+ "Defines for %s use both 'choice' and 'interleave'\n",
+ name, NULL);
+ }
+ } else {
+ xmlRngPErr(ctxt, define->node, XML_RNGP_UNKNOWN_COMBINE,
+ "Defines for %s use unknown combine value '%s''\n",
+ name, combine);
+ }
+ xmlFree(combine);
+ } else {
+ if (missing == 0)
+ missing = 1;
+ else {
+ xmlRngPErr(ctxt, define->node, XML_RNGP_NEED_COMBINE,
+ "Some defines for %s needs the combine attribute\n",
+ name, NULL);
+ }
+ }
+
+ cur = cur->nextHash;
+ }
+#ifdef DEBUG
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlRelaxNGCheckCombine(): merging %s defines: %d\n",
+ name, choiceOrInterleave);
+#endif
+ if (choiceOrInterleave == -1)
+ choiceOrInterleave = 0;
+ cur = xmlRelaxNGNewDefine(ctxt, define->node);
+ if (cur == NULL)
+ return;
+ if (choiceOrInterleave == 0)
+ cur->type = XML_RELAXNG_INTERLEAVE;
+ else
+ cur->type = XML_RELAXNG_CHOICE;
+ tmp = define;
+ last = NULL;
+ while (tmp != NULL) {
+ if (tmp->content != NULL) {
+ if (tmp->content->next != NULL) {
+ /*
+ * we need first to create a wrapper.
+ */
+ tmp2 = xmlRelaxNGNewDefine(ctxt, tmp->content->node);
+ if (tmp2 == NULL)
+ break;
+ tmp2->type = XML_RELAXNG_GROUP;
+ tmp2->content = tmp->content;
+ } else {
+ tmp2 = tmp->content;
+ }
+ if (last == NULL) {
+ cur->content = tmp2;
+ } else {
+ last->next = tmp2;
+ }
+ last = tmp2;
+ }
+ tmp->content = cur;
+ tmp = tmp->nextHash;
+ }
+ define->content = cur;
+ if (choiceOrInterleave == 0) {
+ if (ctxt->interleaves == NULL)
+ ctxt->interleaves = xmlHashCreate(10);
+ if (ctxt->interleaves == NULL) {
+ xmlRngPErr(ctxt, define->node, XML_RNGP_INTERLEAVE_CREATE_FAILED,
+ "Failed to create interleaves hash table\n", NULL,
+ NULL);
+ } else {
+ char tmpname[32];
+
+ snprintf(tmpname, 32, "interleave%d", ctxt->nbInterleaves++);
+ if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST tmpname, cur) <
+ 0) {
+ xmlRngPErr(ctxt, define->node, XML_RNGP_INTERLEAVE_CREATE_FAILED,
+ "Failed to add %s to hash table\n",
+ (const xmlChar *) tmpname, NULL);
+ }
+ }
+ }
+}
+
+/**
+ * xmlRelaxNGCombineStart:
+ * @ctxt: a Relax-NG parser context
+ * @grammar: the grammar
+ *
+ * Applies the 4.17. combine rule for all the start
+ * element of a given grammar.
+ */
+static void
+xmlRelaxNGCombineStart(xmlRelaxNGParserCtxtPtr ctxt,
+ xmlRelaxNGGrammarPtr grammar)
+{
+ xmlRelaxNGDefinePtr starts;
+ xmlChar *combine;
+ int choiceOrInterleave = -1;
+ int missing = 0;
+ xmlRelaxNGDefinePtr cur;
+
+ starts = grammar->start;
+ if ((starts == NULL) || (starts->next == NULL))
+ return;
+ cur = starts;
+ while (cur != NULL) {
+ if ((cur->node == NULL) || (cur->node->parent == NULL) ||
+ (!xmlStrEqual(cur->node->parent->name, BAD_CAST "start"))) {
+ combine = NULL;
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_START_MISSING,
+ "Internal error: start element not found\n", NULL,
+ NULL);
+ } else {
+ combine = xmlGetProp(cur->node->parent, BAD_CAST "combine");
+ }
+
+ if (combine != NULL) {
+ if (xmlStrEqual(combine, BAD_CAST "choice")) {
+ if (choiceOrInterleave == -1)
+ choiceOrInterleave = 1;
+ else if (choiceOrInterleave == 0) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_START_CHOICE_AND_INTERLEAVE,
+ "<start> use both 'choice' and 'interleave'\n",
+ NULL, NULL);
+ }
+ } else if (xmlStrEqual(combine, BAD_CAST "interleave")) {
+ if (choiceOrInterleave == -1)
+ choiceOrInterleave = 0;
+ else if (choiceOrInterleave == 1) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_START_CHOICE_AND_INTERLEAVE,
+ "<start> use both 'choice' and 'interleave'\n",
+ NULL, NULL);
+ }
+ } else {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_UNKNOWN_COMBINE,
+ "<start> uses unknown combine value '%s''\n",
+ combine, NULL);
+ }
+ xmlFree(combine);
+ } else {
+ if (missing == 0)
+ missing = 1;
+ else {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_NEED_COMBINE,
+ "Some <start> element miss the combine attribute\n",
+ NULL, NULL);
+ }
+ }
+
+ cur = cur->next;
+ }
+#ifdef DEBUG
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlRelaxNGCombineStart(): merging <start>: %d\n",
+ choiceOrInterleave);
+#endif
+ if (choiceOrInterleave == -1)
+ choiceOrInterleave = 0;
+ cur = xmlRelaxNGNewDefine(ctxt, starts->node);
+ if (cur == NULL)
+ return;
+ if (choiceOrInterleave == 0)
+ cur->type = XML_RELAXNG_INTERLEAVE;
+ else
+ cur->type = XML_RELAXNG_CHOICE;
+ cur->content = grammar->start;
+ grammar->start = cur;
+ if (choiceOrInterleave == 0) {
+ if (ctxt->interleaves == NULL)
+ ctxt->interleaves = xmlHashCreate(10);
+ if (ctxt->interleaves == NULL) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_INTERLEAVE_CREATE_FAILED,
+ "Failed to create interleaves hash table\n", NULL,
+ NULL);
+ } else {
+ char tmpname[32];
+
+ snprintf(tmpname, 32, "interleave%d", ctxt->nbInterleaves++);
+ if (xmlHashAddEntry(ctxt->interleaves, BAD_CAST tmpname, cur) <
+ 0) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_INTERLEAVE_CREATE_FAILED,
+ "Failed to add %s to hash table\n",
+ (const xmlChar *) tmpname, NULL);
+ }
+ }
+ }
+}
+
+/**
+ * xmlRelaxNGCheckCycles:
+ * @ctxt: a Relax-NG parser context
+ * @nodes: grammar children nodes
+ * @depth: the counter
+ *
+ * Check for cycles.
+ *
+ * Returns 0 if check passed, and -1 in case of error
+ */
+static int
+xmlRelaxNGCheckCycles(xmlRelaxNGParserCtxtPtr ctxt,
+ xmlRelaxNGDefinePtr cur, int depth)
+{
+ int ret = 0;
+
+ while ((ret == 0) && (cur != NULL)) {
+ if ((cur->type == XML_RELAXNG_REF) ||
+ (cur->type == XML_RELAXNG_PARENTREF)) {
+ if (cur->depth == -1) {
+ cur->depth = depth;
+ ret = xmlRelaxNGCheckCycles(ctxt, cur->content, depth);
+ cur->depth = -2;
+ } else if (depth == cur->depth) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_REF_CYCLE,
+ "Detected a cycle in %s references\n",
+ cur->name, NULL);
+ return (-1);
+ }
+ } else if (cur->type == XML_RELAXNG_ELEMENT) {
+ ret = xmlRelaxNGCheckCycles(ctxt, cur->content, depth + 1);
+ } else {
+ ret = xmlRelaxNGCheckCycles(ctxt, cur->content, depth);
+ }
+ cur = cur->next;
+ }
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGTryUnlink:
+ * @ctxt: a Relax-NG parser context
+ * @cur: the definition to unlink
+ * @parent: the parent definition
+ * @prev: the previous sibling definition
+ *
+ * Try to unlink a definition. If not possble make it a NOOP
+ *
+ * Returns the new prev definition
+ */
+static xmlRelaxNGDefinePtr
+xmlRelaxNGTryUnlink(xmlRelaxNGParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
+ xmlRelaxNGDefinePtr cur,
+ xmlRelaxNGDefinePtr parent, xmlRelaxNGDefinePtr prev)
+{
+ if (prev != NULL) {
+ prev->next = cur->next;
+ } else {
+ if (parent != NULL) {
+ if (parent->content == cur)
+ parent->content = cur->next;
+ else if (parent->attrs == cur)
+ parent->attrs = cur->next;
+ else if (parent->nameClass == cur)
+ parent->nameClass = cur->next;
+ } else {
+ cur->type = XML_RELAXNG_NOOP;
+ prev = cur;
+ }
+ }
+ return (prev);
+}
+
+/**
+ * xmlRelaxNGSimplify:
+ * @ctxt: a Relax-NG parser context
+ * @nodes: grammar children nodes
+ *
+ * Check for simplification of empty and notAllowed
+ */
+static void
+xmlRelaxNGSimplify(xmlRelaxNGParserCtxtPtr ctxt,
+ xmlRelaxNGDefinePtr cur, xmlRelaxNGDefinePtr parent)
+{
+ xmlRelaxNGDefinePtr prev = NULL;
+
+ while (cur != NULL) {
+ if ((cur->type == XML_RELAXNG_REF) ||
+ (cur->type == XML_RELAXNG_PARENTREF)) {
+ if (cur->depth != -3) {
+ cur->depth = -3;
+ xmlRelaxNGSimplify(ctxt, cur->content, cur);
+ }
+ } else if (cur->type == XML_RELAXNG_NOT_ALLOWED) {
+ cur->parent = parent;
+ if ((parent != NULL) &&
+ ((parent->type == XML_RELAXNG_ATTRIBUTE) ||
+ (parent->type == XML_RELAXNG_LIST) ||
+ (parent->type == XML_RELAXNG_GROUP) ||
+ (parent->type == XML_RELAXNG_INTERLEAVE) ||
+ (parent->type == XML_RELAXNG_ONEORMORE) ||
+ (parent->type == XML_RELAXNG_ZEROORMORE))) {
+ parent->type = XML_RELAXNG_NOT_ALLOWED;
+ break;
+ }
+ if ((parent != NULL) && (parent->type == XML_RELAXNG_CHOICE)) {
+ prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);
+ } else
+ prev = cur;
+ } else if (cur->type == XML_RELAXNG_EMPTY) {
+ cur->parent = parent;
+ if ((parent != NULL) &&
+ ((parent->type == XML_RELAXNG_ONEORMORE) ||
+ (parent->type == XML_RELAXNG_ZEROORMORE))) {
+ parent->type = XML_RELAXNG_EMPTY;
+ break;
+ }
+ if ((parent != NULL) &&
+ ((parent->type == XML_RELAXNG_GROUP) ||
+ (parent->type == XML_RELAXNG_INTERLEAVE))) {
+ prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);
+ } else
+ prev = cur;
+ } else {
+ cur->parent = parent;
+ if (cur->content != NULL)
+ xmlRelaxNGSimplify(ctxt, cur->content, cur);
+ if ((cur->type != XML_RELAXNG_VALUE) && (cur->attrs != NULL))
+ xmlRelaxNGSimplify(ctxt, cur->attrs, cur);
+ if (cur->nameClass != NULL)
+ xmlRelaxNGSimplify(ctxt, cur->nameClass, cur);
+ /*
+ * On Elements, try to move attribute only generating rules on
+ * the attrs rules.
+ */
+ if (cur->type == XML_RELAXNG_ELEMENT) {
+ int attronly;
+ xmlRelaxNGDefinePtr tmp, pre;
+
+ while (cur->content != NULL) {
+ attronly =
+ xmlRelaxNGGenerateAttributes(ctxt, cur->content);
+ if (attronly == 1) {
+ /*
+ * migrate cur->content to attrs
+ */
+ tmp = cur->content;
+ cur->content = tmp->next;
+ tmp->next = cur->attrs;
+ cur->attrs = tmp;
+ } else {
+ /*
+ * cur->content can generate elements or text
+ */
+ break;
+ }
+ }
+ pre = cur->content;
+ while ((pre != NULL) && (pre->next != NULL)) {
+ tmp = pre->next;
+ attronly = xmlRelaxNGGenerateAttributes(ctxt, tmp);
+ if (attronly == 1) {
+ /*
+ * migrate tmp to attrs
+ */
+ pre->next = tmp->next;
+ tmp->next = cur->attrs;
+ cur->attrs = tmp;
+ } else {
+ pre = tmp;
+ }
+ }
+ }
+ /*
+ * This may result in a simplification
+ */
+ if ((cur->type == XML_RELAXNG_GROUP) ||
+ (cur->type == XML_RELAXNG_INTERLEAVE)) {
+ if (cur->content == NULL)
+ cur->type = XML_RELAXNG_EMPTY;
+ else if (cur->content->next == NULL) {
+ if ((parent == NULL) && (prev == NULL)) {
+ cur->type = XML_RELAXNG_NOOP;
+ } else if (prev == NULL) {
+ parent->content = cur->content;
+ cur->content->next = cur->next;
+ cur = cur->content;
+ } else {
+ cur->content->next = cur->next;
+ prev->next = cur->content;
+ cur = cur->content;
+ }
+ }
+ }
+ /*
+ * the current node may have been transformed back
+ */
+ if ((cur->type == XML_RELAXNG_EXCEPT) &&
+ (cur->content != NULL) &&
+ (cur->content->type == XML_RELAXNG_NOT_ALLOWED)) {
+ prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);
+ } else if (cur->type == XML_RELAXNG_NOT_ALLOWED) {
+ if ((parent != NULL) &&
+ ((parent->type == XML_RELAXNG_ATTRIBUTE) ||
+ (parent->type == XML_RELAXNG_LIST) ||
+ (parent->type == XML_RELAXNG_GROUP) ||
+ (parent->type == XML_RELAXNG_INTERLEAVE) ||
+ (parent->type == XML_RELAXNG_ONEORMORE) ||
+ (parent->type == XML_RELAXNG_ZEROORMORE))) {
+ parent->type = XML_RELAXNG_NOT_ALLOWED;
+ break;
+ }
+ if ((parent != NULL) &&
+ (parent->type == XML_RELAXNG_CHOICE)) {
+ prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);
+ } else
+ prev = cur;
+ } else if (cur->type == XML_RELAXNG_EMPTY) {
+ if ((parent != NULL) &&
+ ((parent->type == XML_RELAXNG_ONEORMORE) ||
+ (parent->type == XML_RELAXNG_ZEROORMORE))) {
+ parent->type = XML_RELAXNG_EMPTY;
+ break;
+ }
+ if ((parent != NULL) &&
+ ((parent->type == XML_RELAXNG_GROUP) ||
+ (parent->type == XML_RELAXNG_INTERLEAVE) ||
+ (parent->type == XML_RELAXNG_CHOICE))) {
+ prev = xmlRelaxNGTryUnlink(ctxt, cur, parent, prev);
+ } else
+ prev = cur;
+ } else {
+ prev = cur;
+ }
+ }
+ cur = cur->next;
+ }
+}
+
+/**
+ * xmlRelaxNGGroupContentType:
+ * @ct1: the first content type
+ * @ct2: the second content type
+ *
+ * Try to group 2 content types
+ *
+ * Returns the content type
+ */
+static xmlRelaxNGContentType
+xmlRelaxNGGroupContentType(xmlRelaxNGContentType ct1,
+ xmlRelaxNGContentType ct2)
+{
+ if ((ct1 == XML_RELAXNG_CONTENT_ERROR) ||
+ (ct2 == XML_RELAXNG_CONTENT_ERROR))
+ return (XML_RELAXNG_CONTENT_ERROR);
+ if (ct1 == XML_RELAXNG_CONTENT_EMPTY)
+ return (ct2);
+ if (ct2 == XML_RELAXNG_CONTENT_EMPTY)
+ return (ct1);
+ if ((ct1 == XML_RELAXNG_CONTENT_COMPLEX) &&
+ (ct2 == XML_RELAXNG_CONTENT_COMPLEX))
+ return (XML_RELAXNG_CONTENT_COMPLEX);
+ return (XML_RELAXNG_CONTENT_ERROR);
+}
+
+/**
+ * xmlRelaxNGMaxContentType:
+ * @ct1: the first content type
+ * @ct2: the second content type
+ *
+ * Compute the max content-type
+ *
+ * Returns the content type
+ */
+static xmlRelaxNGContentType
+xmlRelaxNGMaxContentType(xmlRelaxNGContentType ct1,
+ xmlRelaxNGContentType ct2)
+{
+ if ((ct1 == XML_RELAXNG_CONTENT_ERROR) ||
+ (ct2 == XML_RELAXNG_CONTENT_ERROR))
+ return (XML_RELAXNG_CONTENT_ERROR);
+ if ((ct1 == XML_RELAXNG_CONTENT_SIMPLE) ||
+ (ct2 == XML_RELAXNG_CONTENT_SIMPLE))
+ return (XML_RELAXNG_CONTENT_SIMPLE);
+ if ((ct1 == XML_RELAXNG_CONTENT_COMPLEX) ||
+ (ct2 == XML_RELAXNG_CONTENT_COMPLEX))
+ return (XML_RELAXNG_CONTENT_COMPLEX);
+ return (XML_RELAXNG_CONTENT_EMPTY);
+}
+
+/**
+ * xmlRelaxNGCheckRules:
+ * @ctxt: a Relax-NG parser context
+ * @cur: the current definition
+ * @flags: some accumulated flags
+ * @ptype: the parent type
+ *
+ * Check for rules in section 7.1 and 7.2
+ *
+ * Returns the content type of @cur
+ */
+static xmlRelaxNGContentType
+xmlRelaxNGCheckRules(xmlRelaxNGParserCtxtPtr ctxt,
+ xmlRelaxNGDefinePtr cur, int flags,
+ xmlRelaxNGType ptype)
+{
+ int nflags = flags;
+ xmlRelaxNGContentType ret, tmp, val = XML_RELAXNG_CONTENT_EMPTY;
+
+ while (cur != NULL) {
+ ret = XML_RELAXNG_CONTENT_EMPTY;
+ if ((cur->type == XML_RELAXNG_REF) ||
+ (cur->type == XML_RELAXNG_PARENTREF)) {
+ /*
+ * This should actually be caught by list//element(ref) at the
+ * element boundaries, c.f. Bug #159968 local refs are dropped
+ * in step 4.19.
+ */
+#if 0
+ if (flags & XML_RELAXNG_IN_LIST) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_REF,
+ "Found forbidden pattern list//ref\n", NULL,
+ NULL);
+ }
+#endif
+ if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_REF,
+ "Found forbidden pattern data/except//ref\n",
+ NULL, NULL);
+ }
+ if (cur->depth > -4) {
+ cur->depth = -4;
+ ret = xmlRelaxNGCheckRules(ctxt, cur->content,
+ flags, cur->type);
+ cur->depth = ret - 15;
+ } else if (cur->depth == -4) {
+ ret = XML_RELAXNG_CONTENT_COMPLEX;
+ } else {
+ ret = (xmlRelaxNGContentType) (cur->depth + 15);
+ }
+ } else if (cur->type == XML_RELAXNG_ELEMENT) {
+ /*
+ * The 7.3 Attribute derivation rule for groups is plugged there
+ */
+ xmlRelaxNGCheckGroupAttrs(ctxt, cur);
+ if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_ELEM,
+ "Found forbidden pattern data/except//element(ref)\n",
+ NULL, NULL);
+ }
+ if (flags & XML_RELAXNG_IN_LIST) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_ELEM,
+ "Found forbidden pattern list//element(ref)\n",
+ NULL, NULL);
+ }
+ if (flags & XML_RELAXNG_IN_ATTRIBUTE) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ATTR_ELEM,
+ "Found forbidden pattern attribute//element(ref)\n",
+ NULL, NULL);
+ }
+ if (flags & XML_RELAXNG_IN_ATTRIBUTE) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ATTR_ELEM,
+ "Found forbidden pattern attribute//element(ref)\n",
+ NULL, NULL);
+ }
+ /*
+ * reset since in the simple form elements are only child
+ * of grammar/define
+ */
+ nflags = 0;
+ ret =
+ xmlRelaxNGCheckRules(ctxt, cur->attrs, nflags, cur->type);
+ if (ret != XML_RELAXNG_CONTENT_EMPTY) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_ELEM_CONTENT_EMPTY,
+ "Element %s attributes have a content type error\n",
+ cur->name, NULL);
+ }
+ ret =
+ xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
+ cur->type);
+ if (ret == XML_RELAXNG_CONTENT_ERROR) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_ELEM_CONTENT_ERROR,
+ "Element %s has a content type error\n",
+ cur->name, NULL);
+ } else {
+ ret = XML_RELAXNG_CONTENT_COMPLEX;
+ }
+ } else if (cur->type == XML_RELAXNG_ATTRIBUTE) {
+ if (flags & XML_RELAXNG_IN_ATTRIBUTE) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ATTR_ATTR,
+ "Found forbidden pattern attribute//attribute\n",
+ NULL, NULL);
+ }
+ if (flags & XML_RELAXNG_IN_LIST) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_ATTR,
+ "Found forbidden pattern list//attribute\n",
+ NULL, NULL);
+ }
+ if (flags & XML_RELAXNG_IN_OOMGROUP) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ONEMORE_GROUP_ATTR,
+ "Found forbidden pattern oneOrMore//group//attribute\n",
+ NULL, NULL);
+ }
+ if (flags & XML_RELAXNG_IN_OOMINTERLEAVE) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_ONEMORE_INTERLEAVE_ATTR,
+ "Found forbidden pattern oneOrMore//interleave//attribute\n",
+ NULL, NULL);
+ }
+ if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_ATTR,
+ "Found forbidden pattern data/except//attribute\n",
+ NULL, NULL);
+ }
+ if (flags & XML_RELAXNG_IN_START) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_ATTR,
+ "Found forbidden pattern start//attribute\n",
+ NULL, NULL);
+ }
+ if ((!(flags & XML_RELAXNG_IN_ONEORMORE))
+ && (cur->name == NULL)) {
+ if (cur->ns == NULL) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_ANYNAME_ATTR_ANCESTOR,
+ "Found anyName attribute without oneOrMore ancestor\n",
+ NULL, NULL);
+ } else {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_NSNAME_ATTR_ANCESTOR,
+ "Found nsName attribute without oneOrMore ancestor\n",
+ NULL, NULL);
+ }
+ }
+ nflags = flags | XML_RELAXNG_IN_ATTRIBUTE;
+ xmlRelaxNGCheckRules(ctxt, cur->content, nflags, cur->type);
+ ret = XML_RELAXNG_CONTENT_EMPTY;
+ } else if ((cur->type == XML_RELAXNG_ONEORMORE) ||
+ (cur->type == XML_RELAXNG_ZEROORMORE)) {
+ if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_ONEMORE,
+ "Found forbidden pattern data/except//oneOrMore\n",
+ NULL, NULL);
+ }
+ if (flags & XML_RELAXNG_IN_START) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_ONEMORE,
+ "Found forbidden pattern start//oneOrMore\n",
+ NULL, NULL);
+ }
+ nflags = flags | XML_RELAXNG_IN_ONEORMORE;
+ ret =
+ xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
+ cur->type);
+ ret = xmlRelaxNGGroupContentType(ret, ret);
+ } else if (cur->type == XML_RELAXNG_LIST) {
+ if (flags & XML_RELAXNG_IN_LIST) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_LIST,
+ "Found forbidden pattern list//list\n", NULL,
+ NULL);
+ }
+ if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_LIST,
+ "Found forbidden pattern data/except//list\n",
+ NULL, NULL);
+ }
+ if (flags & XML_RELAXNG_IN_START) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_LIST,
+ "Found forbidden pattern start//list\n", NULL,
+ NULL);
+ }
+ nflags = flags | XML_RELAXNG_IN_LIST;
+ ret =
+ xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
+ cur->type);
+ } else if (cur->type == XML_RELAXNG_GROUP) {
+ if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_GROUP,
+ "Found forbidden pattern data/except//group\n",
+ NULL, NULL);
+ }
+ if (flags & XML_RELAXNG_IN_START) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_GROUP,
+ "Found forbidden pattern start//group\n", NULL,
+ NULL);
+ }
+ if (flags & XML_RELAXNG_IN_ONEORMORE)
+ nflags = flags | XML_RELAXNG_IN_OOMGROUP;
+ else
+ nflags = flags;
+ ret =
+ xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
+ cur->type);
+ /*
+ * The 7.3 Attribute derivation rule for groups is plugged there
+ */
+ xmlRelaxNGCheckGroupAttrs(ctxt, cur);
+ } else if (cur->type == XML_RELAXNG_INTERLEAVE) {
+ if (flags & XML_RELAXNG_IN_LIST) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_INTERLEAVE,
+ "Found forbidden pattern list//interleave\n",
+ NULL, NULL);
+ }
+ if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_INTERLEAVE,
+ "Found forbidden pattern data/except//interleave\n",
+ NULL, NULL);
+ }
+ if (flags & XML_RELAXNG_IN_START) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_INTERLEAVE,
+ "Found forbidden pattern start//interleave\n",
+ NULL, NULL);
+ }
+ if (flags & XML_RELAXNG_IN_ONEORMORE)
+ nflags = flags | XML_RELAXNG_IN_OOMINTERLEAVE;
+ else
+ nflags = flags;
+ ret =
+ xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
+ cur->type);
+ } else if (cur->type == XML_RELAXNG_EXCEPT) {
+ if ((cur->parent != NULL) &&
+ (cur->parent->type == XML_RELAXNG_DATATYPE))
+ nflags = flags | XML_RELAXNG_IN_DATAEXCEPT;
+ else
+ nflags = flags;
+ ret =
+ xmlRelaxNGCheckRules(ctxt, cur->content, nflags,
+ cur->type);
+ } else if (cur->type == XML_RELAXNG_DATATYPE) {
+ if (flags & XML_RELAXNG_IN_START) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_DATA,
+ "Found forbidden pattern start//data\n", NULL,
+ NULL);
+ }
+ xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);
+ ret = XML_RELAXNG_CONTENT_SIMPLE;
+ } else if (cur->type == XML_RELAXNG_VALUE) {
+ if (flags & XML_RELAXNG_IN_START) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_VALUE,
+ "Found forbidden pattern start//value\n", NULL,
+ NULL);
+ }
+ xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);
+ ret = XML_RELAXNG_CONTENT_SIMPLE;
+ } else if (cur->type == XML_RELAXNG_TEXT) {
+ if (flags & XML_RELAXNG_IN_LIST) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_LIST_TEXT,
+ "Found forbidden pattern list//text\n", NULL,
+ NULL);
+ }
+ if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_TEXT,
+ "Found forbidden pattern data/except//text\n",
+ NULL, NULL);
+ }
+ if (flags & XML_RELAXNG_IN_START) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_TEXT,
+ "Found forbidden pattern start//text\n", NULL,
+ NULL);
+ }
+ ret = XML_RELAXNG_CONTENT_COMPLEX;
+ } else if (cur->type == XML_RELAXNG_EMPTY) {
+ if (flags & XML_RELAXNG_IN_DATAEXCEPT) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_DATA_EXCEPT_EMPTY,
+ "Found forbidden pattern data/except//empty\n",
+ NULL, NULL);
+ }
+ if (flags & XML_RELAXNG_IN_START) {
+ xmlRngPErr(ctxt, cur->node, XML_RNGP_PAT_START_EMPTY,
+ "Found forbidden pattern start//empty\n", NULL,
+ NULL);
+ }
+ ret = XML_RELAXNG_CONTENT_EMPTY;
+ } else if (cur->type == XML_RELAXNG_CHOICE) {
+ xmlRelaxNGCheckChoiceDeterminism(ctxt, cur);
+ ret =
+ xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);
+ } else {
+ ret =
+ xmlRelaxNGCheckRules(ctxt, cur->content, flags, cur->type);
+ }
+ cur = cur->next;
+ if (ptype == XML_RELAXNG_GROUP) {
+ val = xmlRelaxNGGroupContentType(val, ret);
+ } else if (ptype == XML_RELAXNG_INTERLEAVE) {
+ tmp = xmlRelaxNGGroupContentType(val, ret);
+ if (tmp != XML_RELAXNG_CONTENT_ERROR)
+ tmp = xmlRelaxNGMaxContentType(val, ret);
+ } else if (ptype == XML_RELAXNG_CHOICE) {
+ val = xmlRelaxNGMaxContentType(val, ret);
+ } else if (ptype == XML_RELAXNG_LIST) {
+ val = XML_RELAXNG_CONTENT_SIMPLE;
+ } else if (ptype == XML_RELAXNG_EXCEPT) {
+ if (ret == XML_RELAXNG_CONTENT_ERROR)
+ val = XML_RELAXNG_CONTENT_ERROR;
+ else
+ val = XML_RELAXNG_CONTENT_SIMPLE;
+ } else {
+ val = xmlRelaxNGGroupContentType(val, ret);
+ }
+
+ }
+ return (val);
+}
+
+/**
+ * xmlRelaxNGParseGrammar:
+ * @ctxt: a Relax-NG parser context
+ * @nodes: grammar children nodes
+ *
+ * parse a Relax-NG <grammar> node
+ *
+ * Returns the internal xmlRelaxNGGrammarPtr built or
+ * NULL in case of error
+ */
+static xmlRelaxNGGrammarPtr
+xmlRelaxNGParseGrammar(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes)
+{
+ xmlRelaxNGGrammarPtr ret, tmp, old;
+
+#ifdef DEBUG_GRAMMAR
+ xmlGenericError(xmlGenericErrorContext, "Parsing a new grammar\n");
+#endif
+
+ ret = xmlRelaxNGNewGrammar(ctxt);
+ if (ret == NULL)
+ return (NULL);
+
+ /*
+ * Link the new grammar in the tree
+ */
+ ret->parent = ctxt->grammar;
+ if (ctxt->grammar != NULL) {
+ tmp = ctxt->grammar->children;
+ if (tmp == NULL) {
+ ctxt->grammar->children = ret;
+ } else {
+ while (tmp->next != NULL)
+ tmp = tmp->next;
+ tmp->next = ret;
+ }
+ }
+
+ old = ctxt->grammar;
+ ctxt->grammar = ret;
+ xmlRelaxNGParseGrammarContent(ctxt, nodes);
+ ctxt->grammar = ret;
+ if (ctxt->grammar == NULL) {
+ xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_CONTENT,
+ "Failed to parse <grammar> content\n", NULL, NULL);
+ } else if (ctxt->grammar->start == NULL) {
+ xmlRngPErr(ctxt, nodes, XML_RNGP_GRAMMAR_NO_START,
+ "Element <grammar> has no <start>\n", NULL, NULL);
+ }
+
+ /*
+ * Apply 4.17 mergingd rules to defines and starts
+ */
+ xmlRelaxNGCombineStart(ctxt, ret);
+ if (ret->defs != NULL) {
+ xmlHashScan(ret->defs, (xmlHashScanner) xmlRelaxNGCheckCombine,
+ ctxt);
+ }
+
+ /*
+ * link together defines and refs in this grammar
+ */
+ if (ret->refs != NULL) {
+ xmlHashScan(ret->refs, (xmlHashScanner) xmlRelaxNGCheckReference,
+ ctxt);
+ }
+
+ ctxt->grammar = old;
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGParseDocument:
+ * @ctxt: a Relax-NG parser context
+ * @node: the root node of the RelaxNG schema
+ *
+ * parse a Relax-NG definition resource and build an internal
+ * xmlRelaxNG struture which can be used to validate instances.
+ *
+ * Returns the internal XML RelaxNG structure built or
+ * NULL in case of error
+ */
+static xmlRelaxNGPtr
+xmlRelaxNGParseDocument(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
+{
+ xmlRelaxNGPtr schema = NULL;
+ const xmlChar *olddefine;
+ xmlRelaxNGGrammarPtr old;
+
+ if ((ctxt == NULL) || (node == NULL))
+ return (NULL);
+
+ schema = xmlRelaxNGNewRelaxNG(ctxt);
+ if (schema == NULL)
+ return (NULL);
+
+ olddefine = ctxt->define;
+ ctxt->define = NULL;
+ if (IS_RELAXNG(node, "grammar")) {
+ schema->topgrammar = xmlRelaxNGParseGrammar(ctxt, node->children);
+ } else {
+ xmlRelaxNGGrammarPtr tmp, ret;
+
+ schema->topgrammar = ret = xmlRelaxNGNewGrammar(ctxt);
+ if (schema->topgrammar == NULL) {
+ return (schema);
+ }
+ /*
+ * Link the new grammar in the tree
+ */
+ ret->parent = ctxt->grammar;
+ if (ctxt->grammar != NULL) {
+ tmp = ctxt->grammar->children;
+ if (tmp == NULL) {
+ ctxt->grammar->children = ret;
+ } else {
+ while (tmp->next != NULL)
+ tmp = tmp->next;
+ tmp->next = ret;
+ }
+ }
+ old = ctxt->grammar;
+ ctxt->grammar = ret;
+ xmlRelaxNGParseStart(ctxt, node);
+ if (old != NULL)
+ ctxt->grammar = old;
+ }
+ ctxt->define = olddefine;
+ if (schema->topgrammar->start != NULL) {
+ xmlRelaxNGCheckCycles(ctxt, schema->topgrammar->start, 0);
+ if ((ctxt->flags & XML_RELAXNG_IN_EXTERNALREF) == 0) {
+ xmlRelaxNGSimplify(ctxt, schema->topgrammar->start, NULL);
+ while ((schema->topgrammar->start != NULL) &&
+ (schema->topgrammar->start->type == XML_RELAXNG_NOOP) &&
+ (schema->topgrammar->start->next != NULL))
+ schema->topgrammar->start =
+ schema->topgrammar->start->content;
+ xmlRelaxNGCheckRules(ctxt, schema->topgrammar->start,
+ XML_RELAXNG_IN_START, XML_RELAXNG_NOOP);
+ }
+ }
+#ifdef DEBUG
+ if (schema == NULL)
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlRelaxNGParseDocument() failed\n");
+#endif
+
+ return (schema);
+}
+
+/************************************************************************
+ * *
+ * Reading RelaxNGs *
+ * *
+ ************************************************************************/
+
+/**
+ * xmlRelaxNGNewParserCtxt:
+ * @URL: the location of the schema
+ *
+ * Create an XML RelaxNGs parse context for that file/resource expected
+ * to contain an XML RelaxNGs file.
+ *
+ * Returns the parser context or NULL in case of error
+ */
+xmlRelaxNGParserCtxtPtr
+xmlRelaxNGNewParserCtxt(const char *URL)
+{
+ xmlRelaxNGParserCtxtPtr ret;
+
+ if (URL == NULL)
+ return (NULL);
+
+ ret =
+ (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt));
+ if (ret == NULL) {
+ xmlRngPErrMemory(NULL, "building parser\n");
+ return (NULL);
+ }
+ memset(ret, 0, sizeof(xmlRelaxNGParserCtxt));
+ ret->URL = xmlStrdup((const xmlChar *) URL);
+ ret->error = xmlGenericError;
+ ret->userData = xmlGenericErrorContext;
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGNewMemParserCtxt:
+ * @buffer: a pointer to a char array containing the schemas
+ * @size: the size of the array
+ *
+ * Create an XML RelaxNGs parse context for that memory buffer expected
+ * to contain an XML RelaxNGs file.
+ *
+ * Returns the parser context or NULL in case of error
+ */
+xmlRelaxNGParserCtxtPtr
+xmlRelaxNGNewMemParserCtxt(const char *buffer, int size)
+{
+ xmlRelaxNGParserCtxtPtr ret;
+
+ if ((buffer == NULL) || (size <= 0))
+ return (NULL);
+
+ ret =
+ (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt));
+ if (ret == NULL) {
+ xmlRngPErrMemory(NULL, "building parser\n");
+ return (NULL);
+ }
+ memset(ret, 0, sizeof(xmlRelaxNGParserCtxt));
+ ret->buffer = buffer;
+ ret->size = size;
+ ret->error = xmlGenericError;
+ ret->userData = xmlGenericErrorContext;
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGNewDocParserCtxt:
+ * @doc: a preparsed document tree
+ *
+ * Create an XML RelaxNGs parser context for that document.
+ * Note: since the process of compiling a RelaxNG schemas modifies the
+ * document, the @doc parameter is duplicated internally.
+ *
+ * Returns the parser context or NULL in case of error
+ */
+xmlRelaxNGParserCtxtPtr
+xmlRelaxNGNewDocParserCtxt(xmlDocPtr doc)
+{
+ xmlRelaxNGParserCtxtPtr ret;
+ xmlDocPtr copy;
+
+ if (doc == NULL)
+ return (NULL);
+ copy = xmlCopyDoc(doc, 1);
+ if (copy == NULL)
+ return (NULL);
+
+ ret =
+ (xmlRelaxNGParserCtxtPtr) xmlMalloc(sizeof(xmlRelaxNGParserCtxt));
+ if (ret == NULL) {
+ xmlRngPErrMemory(NULL, "building parser\n");
+ return (NULL);
+ }
+ memset(ret, 0, sizeof(xmlRelaxNGParserCtxt));
+ ret->document = copy;
+ ret->freedoc = 1;
+ ret->userData = xmlGenericErrorContext;
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGFreeParserCtxt:
+ * @ctxt: the schema parser context
+ *
+ * Free the resources associated to the schema parser context
+ */
+void
+xmlRelaxNGFreeParserCtxt(xmlRelaxNGParserCtxtPtr ctxt)
+{
+ if (ctxt == NULL)
+ return;
+ if (ctxt->URL != NULL)
+ xmlFree(ctxt->URL);
+ if (ctxt->doc != NULL)
+ xmlRelaxNGFreeDocument(ctxt->doc);
+ if (ctxt->interleaves != NULL)
+ xmlHashFree(ctxt->interleaves, NULL);
+ if (ctxt->documents != NULL)
+ xmlRelaxNGFreeDocumentList(ctxt->documents);
+ if (ctxt->includes != NULL)
+ xmlRelaxNGFreeIncludeList(ctxt->includes);
+ if (ctxt->docTab != NULL)
+ xmlFree(ctxt->docTab);
+ if (ctxt->incTab != NULL)
+ xmlFree(ctxt->incTab);
+ if (ctxt->defTab != NULL) {
+ int i;
+
+ for (i = 0; i < ctxt->defNr; i++)
+ xmlRelaxNGFreeDefine(ctxt->defTab[i]);
+ xmlFree(ctxt->defTab);
+ }
+ if ((ctxt->document != NULL) && (ctxt->freedoc))
+ xmlFreeDoc(ctxt->document);
+ xmlFree(ctxt);
+}
+
+/**
+ * xmlRelaxNGNormExtSpace:
+ * @value: a value
+ *
+ * Removes the leading and ending spaces of the value
+ * The string is modified "in situ"
+ */
+static void
+xmlRelaxNGNormExtSpace(xmlChar * value)
+{
+ xmlChar *start = value;
+ xmlChar *cur = value;
+
+ if (value == NULL)
+ return;
+
+ while (IS_BLANK_CH(*cur))
+ cur++;
+ if (cur == start) {
+ do {
+ while ((*cur != 0) && (!IS_BLANK_CH(*cur)))
+ cur++;
+ if (*cur == 0)
+ return;
+ start = cur;
+ while (IS_BLANK_CH(*cur))
+ cur++;
+ if (*cur == 0) {
+ *start = 0;
+ return;
+ }
+ } while (1);
+ } else {
+ do {
+ while ((*cur != 0) && (!IS_BLANK_CH(*cur)))
+ *start++ = *cur++;
+ if (*cur == 0) {
+ *start = 0;
+ return;
+ }
+ /* don't try to normalize the inner spaces */
+ while (IS_BLANK_CH(*cur))
+ cur++;
+ if (*cur == 0) {
+ *start = 0;
+ return;
+ }
+ *start++ = *cur++;
+ } while (1);
+ }
+}
+
+/**
+ * xmlRelaxNGCleanupAttributes:
+ * @ctxt: a Relax-NG parser context
+ * @node: a Relax-NG node
+ *
+ * Check all the attributes on the given node
+ */
+static void
+xmlRelaxNGCleanupAttributes(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node)
+{
+ xmlAttrPtr cur, next;
+
+ cur = node->properties;
+ while (cur != NULL) {
+ next = cur->next;
+ if ((cur->ns == NULL) ||
+ (xmlStrEqual(cur->ns->href, xmlRelaxNGNs))) {
+ if (xmlStrEqual(cur->name, BAD_CAST "name")) {
+ if ((!xmlStrEqual(node->name, BAD_CAST "element")) &&
+ (!xmlStrEqual(node->name, BAD_CAST "attribute")) &&
+ (!xmlStrEqual(node->name, BAD_CAST "ref")) &&
+ (!xmlStrEqual(node->name, BAD_CAST "parentRef")) &&
+ (!xmlStrEqual(node->name, BAD_CAST "param")) &&
+ (!xmlStrEqual(node->name, BAD_CAST "define"))) {
+ xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,
+ "Attribute %s is not allowed on %s\n",
+ cur->name, node->name);
+ }
+ } else if (xmlStrEqual(cur->name, BAD_CAST "type")) {
+ if ((!xmlStrEqual(node->name, BAD_CAST "value")) &&
+ (!xmlStrEqual(node->name, BAD_CAST "data"))) {
+ xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,
+ "Attribute %s is not allowed on %s\n",
+ cur->name, node->name);
+ }
+ } else if (xmlStrEqual(cur->name, BAD_CAST "href")) {
+ if ((!xmlStrEqual(node->name, BAD_CAST "externalRef")) &&
+ (!xmlStrEqual(node->name, BAD_CAST "include"))) {
+ xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,
+ "Attribute %s is not allowed on %s\n",
+ cur->name, node->name);
+ }
+ } else if (xmlStrEqual(cur->name, BAD_CAST "combine")) {
+ if ((!xmlStrEqual(node->name, BAD_CAST "start")) &&
+ (!xmlStrEqual(node->name, BAD_CAST "define"))) {
+ xmlRngPErr(ctxt, node, XML_RNGP_FORBIDDEN_ATTRIBUTE,
+ "Attribute %s is not allowed on %s\n",
+ cur->name, node->name);
+ }
+ } else if (xmlStrEqual(cur->name, BAD_CAST "datatypeLibrary")) {
+ xmlChar *val;
+ xmlURIPtr uri;
+
+ val = xmlNodeListGetString(node->doc, cur->children, 1);
+ if (val != NULL) {
+ if (val[0] != 0) {
+ uri = xmlParseURI((const char *) val);
+ if (uri == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_INVALID_URI,
+ "Attribute %s contains invalid URI %s\n",
+ cur->name, val);
+ } else {
+ if (uri->scheme == NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_URI_NOT_ABSOLUTE,
+ "Attribute %s URI %s is not absolute\n",
+ cur->name, val);
+ }
+ if (uri->fragment != NULL) {
+ xmlRngPErr(ctxt, node, XML_RNGP_URI_FRAGMENT,
+ "Attribute %s URI %s has a fragment ID\n",
+ cur->name, val);
+ }
+ xmlFreeURI(uri);
+ }
+ }
+ xmlFree(val);
+ }
+ } else if (!xmlStrEqual(cur->name, BAD_CAST "ns")) {
+ xmlRngPErr(ctxt, node, XML_RNGP_UNKNOWN_ATTRIBUTE,
+ "Unknown attribute %s on %s\n", cur->name,
+ node->name);
+ }
+ }
+ cur = next;
+ }
+}
+
+/**
+ * xmlRelaxNGCleanupTree:
+ * @ctxt: a Relax-NG parser context
+ * @root: an xmlNodePtr subtree
+ *
+ * Cleanup the subtree from unwanted nodes for parsing, resolve
+ * Include and externalRef lookups.
+ */
+static void
+xmlRelaxNGCleanupTree(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr root)
+{
+ xmlNodePtr cur, delete;
+
+ delete = NULL;
+ cur = root;
+ while (cur != NULL) {
+ if (delete != NULL) {
+ xmlUnlinkNode(delete);
+ xmlFreeNode(delete);
+ delete = NULL;
+ }
+ if (cur->type == XML_ELEMENT_NODE) {
+ /*
+ * Simplification 4.1. Annotations
+ */
+ if ((cur->ns == NULL) ||
+ (!xmlStrEqual(cur->ns->href, xmlRelaxNGNs))) {
+ if ((cur->parent != NULL) &&
+ (cur->parent->type == XML_ELEMENT_NODE) &&
+ ((xmlStrEqual(cur->parent->name, BAD_CAST "name")) ||
+ (xmlStrEqual(cur->parent->name, BAD_CAST "value")) ||
+ (xmlStrEqual(cur->parent->name, BAD_CAST "param")))) {
+ xmlRngPErr(ctxt, cur, XML_RNGP_FOREIGN_ELEMENT,
+ "element %s doesn't allow foreign elements\n",
+ cur->parent->name, NULL);
+ }
+ delete = cur;
+ goto skip_children;
+ } else {
+ xmlRelaxNGCleanupAttributes(ctxt, cur);
+ if (xmlStrEqual(cur->name, BAD_CAST "externalRef")) {
+ xmlChar *href, *ns, *base, *URL;
+ xmlRelaxNGDocumentPtr docu;
+ xmlNodePtr tmp;
+ xmlURIPtr uri;
+
+ ns = xmlGetProp(cur, BAD_CAST "ns");
+ if (ns == NULL) {
+ tmp = cur->parent;
+ while ((tmp != NULL) &&
+ (tmp->type == XML_ELEMENT_NODE)) {
+ ns = xmlGetProp(tmp, BAD_CAST "ns");
+ if (ns != NULL)
+ break;
+ tmp = tmp->parent;
+ }
+ }
+ href = xmlGetProp(cur, BAD_CAST "href");
+ if (href == NULL) {
+ xmlRngPErr(ctxt, cur, XML_RNGP_MISSING_HREF,
+ "xmlRelaxNGParse: externalRef has no href attribute\n",
+ NULL, NULL);
+ if (ns != NULL)
+ xmlFree(ns);
+ delete = cur;
+ goto skip_children;
+ }
+ uri = xmlParseURI((const char *) href);
+ if (uri == NULL) {
+ xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR,
+ "Incorrect URI for externalRef %s\n",
+ href, NULL);
+ if (ns != NULL)
+ xmlFree(ns);
+ if (href != NULL)
+ xmlFree(href);
+ delete = cur;
+ goto skip_children;
+ }
+ if (uri->fragment != NULL) {
+ xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR,
+ "Fragment forbidden in URI for externalRef %s\n",
+ href, NULL);
+ if (ns != NULL)
+ xmlFree(ns);
+ xmlFreeURI(uri);
+ if (href != NULL)
+ xmlFree(href);
+ delete = cur;
+ goto skip_children;
+ }
+ xmlFreeURI(uri);
+ base = xmlNodeGetBase(cur->doc, cur);
+ URL = xmlBuildURI(href, base);
+ if (URL == NULL) {
+ xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR,
+ "Failed to compute URL for externalRef %s\n",
+ href, NULL);
+ if (ns != NULL)
+ xmlFree(ns);
+ if (href != NULL)
+ xmlFree(href);
+ if (base != NULL)
+ xmlFree(base);
+ delete = cur;
+ goto skip_children;
+ }
+ if (href != NULL)
+ xmlFree(href);
+ if (base != NULL)
+ xmlFree(base);
+ docu = xmlRelaxNGLoadExternalRef(ctxt, URL, ns);
+ if (docu == NULL) {
+ xmlRngPErr(ctxt, cur, XML_RNGP_EXTERNAL_REF_FAILURE,
+ "Failed to load externalRef %s\n", URL,
+ NULL);
+ if (ns != NULL)
+ xmlFree(ns);
+ xmlFree(URL);
+ delete = cur;
+ goto skip_children;
+ }
+ if (ns != NULL)
+ xmlFree(ns);
+ xmlFree(URL);
+ cur->psvi = docu;
+ } else if (xmlStrEqual(cur->name, BAD_CAST "include")) {
+ xmlChar *href, *ns, *base, *URL;
+ xmlRelaxNGIncludePtr incl;
+ xmlNodePtr tmp;
+
+ href = xmlGetProp(cur, BAD_CAST "href");
+ if (href == NULL) {
+ xmlRngPErr(ctxt, cur, XML_RNGP_MISSING_HREF,
+ "xmlRelaxNGParse: include has no href attribute\n",
+ NULL, NULL);
+ delete = cur;
+ goto skip_children;
+ }
+ base = xmlNodeGetBase(cur->doc, cur);
+ URL = xmlBuildURI(href, base);
+ if (URL == NULL) {
+ xmlRngPErr(ctxt, cur, XML_RNGP_HREF_ERROR,
+ "Failed to compute URL for include %s\n",
+ href, NULL);
+ if (href != NULL)
+ xmlFree(href);
+ if (base != NULL)
+ xmlFree(base);
+ delete = cur;
+ goto skip_children;
+ }
+ if (href != NULL)
+ xmlFree(href);
+ if (base != NULL)
+ xmlFree(base);
+ ns = xmlGetProp(cur, BAD_CAST "ns");
+ if (ns == NULL) {
+ tmp = cur->parent;
+ while ((tmp != NULL) &&
+ (tmp->type == XML_ELEMENT_NODE)) {
+ ns = xmlGetProp(tmp, BAD_CAST "ns");
+ if (ns != NULL)
+ break;
+ tmp = tmp->parent;
+ }
+ }
+ incl = xmlRelaxNGLoadInclude(ctxt, URL, cur, ns);
+ if (ns != NULL)
+ xmlFree(ns);
+ if (incl == NULL) {
+ xmlRngPErr(ctxt, cur, XML_RNGP_INCLUDE_FAILURE,
+ "Failed to load include %s\n", URL,
+ NULL);
+ xmlFree(URL);
+ delete = cur;
+ goto skip_children;
+ }
+ xmlFree(URL);
+ cur->psvi = incl;
+ } else if ((xmlStrEqual(cur->name, BAD_CAST "element")) ||
+ (xmlStrEqual(cur->name, BAD_CAST "attribute")))
+ {
+ xmlChar *name, *ns;
+ xmlNodePtr text = NULL;
+
+ /*
+ * Simplification 4.8. name attribute of element
+ * and attribute elements
+ */
+ name = xmlGetProp(cur, BAD_CAST "name");
+ if (name != NULL) {
+ if (cur->children == NULL) {
+ text =
+ xmlNewChild(cur, cur->ns, BAD_CAST "name",
+ name);
+ } else {
+ xmlNodePtr node;
+
+ node = xmlNewDocNode(cur->doc, cur->ns,
+ BAD_CAST "name", NULL);
+ if (node != NULL) {
+ xmlAddPrevSibling(cur->children, node);
+ text = xmlNewText(name);
+ xmlAddChild(node, text);
+ text = node;
+ }
+ }
+ if (text == NULL) {
+ xmlRngPErr(ctxt, cur, XML_RNGP_CREATE_FAILURE,
+ "Failed to create a name %s element\n",
+ name, NULL);
+ }
+ xmlUnsetProp(cur, BAD_CAST "name");
+ xmlFree(name);
+ ns = xmlGetProp(cur, BAD_CAST "ns");
+ if (ns != NULL) {
+ if (text != NULL) {
+ xmlSetProp(text, BAD_CAST "ns", ns);
+ /* xmlUnsetProp(cur, BAD_CAST "ns"); */
+ }
+ xmlFree(ns);
+ } else if (xmlStrEqual(cur->name,
+ BAD_CAST "attribute")) {
+ xmlSetProp(text, BAD_CAST "ns", BAD_CAST "");
+ }
+ }
+ } else if ((xmlStrEqual(cur->name, BAD_CAST "name")) ||
+ (xmlStrEqual(cur->name, BAD_CAST "nsName")) ||
+ (xmlStrEqual(cur->name, BAD_CAST "value"))) {
+ /*
+ * Simplification 4.8. name attribute of element
+ * and attribute elements
+ */
+ if (xmlHasProp(cur, BAD_CAST "ns") == NULL) {
+ xmlNodePtr node;
+ xmlChar *ns = NULL;
+
+ node = cur->parent;
+ while ((node != NULL) &&
+ (node->type == XML_ELEMENT_NODE)) {
+ ns = xmlGetProp(node, BAD_CAST "ns");
+ if (ns != NULL) {
+ break;
+ }
+ node = node->parent;
+ }
+ if (ns == NULL) {
+ xmlSetProp(cur, BAD_CAST "ns", BAD_CAST "");
+ } else {
+ xmlSetProp(cur, BAD_CAST "ns", ns);
+ xmlFree(ns);
+ }
+ }
+ if (xmlStrEqual(cur->name, BAD_CAST "name")) {
+ xmlChar *name, *local, *prefix;
+
+ /*
+ * Simplification: 4.10. QNames
+ */
+ name = xmlNodeGetContent(cur);
+ if (name != NULL) {
+ local = xmlSplitQName2(name, &prefix);
+ if (local != NULL) {
+ xmlNsPtr ns;
+
+ ns = xmlSearchNs(cur->doc, cur, prefix);
+ if (ns == NULL) {
+ xmlRngPErr(ctxt, cur,
+ XML_RNGP_PREFIX_UNDEFINED,
+ "xmlRelaxNGParse: no namespace for prefix %s\n",
+ prefix, NULL);
+ } else {
+ xmlSetProp(cur, BAD_CAST "ns",
+ ns->href);
+ xmlNodeSetContent(cur, local);
+ }
+ xmlFree(local);
+ xmlFree(prefix);
+ }
+ xmlFree(name);
+ }
+ }
+ /*
+ * 4.16
+ */
+ if (xmlStrEqual(cur->name, BAD_CAST "nsName")) {
+ if (ctxt->flags & XML_RELAXNG_IN_NSEXCEPT) {
+ xmlRngPErr(ctxt, cur,
+ XML_RNGP_PAT_NSNAME_EXCEPT_NSNAME,
+ "Found nsName/except//nsName forbidden construct\n",
+ NULL, NULL);
+ }
+ }
+ } else if ((xmlStrEqual(cur->name, BAD_CAST "except")) &&
+ (cur != root)) {
+ int oldflags = ctxt->flags;
+
+ /*
+ * 4.16
+ */
+ if ((cur->parent != NULL) &&
+ (xmlStrEqual
+ (cur->parent->name, BAD_CAST "anyName"))) {
+ ctxt->flags |= XML_RELAXNG_IN_ANYEXCEPT;
+ xmlRelaxNGCleanupTree(ctxt, cur);
+ ctxt->flags = oldflags;
+ goto skip_children;
+ } else if ((cur->parent != NULL) &&
+ (xmlStrEqual
+ (cur->parent->name, BAD_CAST "nsName"))) {
+ ctxt->flags |= XML_RELAXNG_IN_NSEXCEPT;
+ xmlRelaxNGCleanupTree(ctxt, cur);
+ ctxt->flags = oldflags;
+ goto skip_children;
+ }
+ } else if (xmlStrEqual(cur->name, BAD_CAST "anyName")) {
+ /*
+ * 4.16
+ */
+ if (ctxt->flags & XML_RELAXNG_IN_ANYEXCEPT) {
+ xmlRngPErr(ctxt, cur,
+ XML_RNGP_PAT_ANYNAME_EXCEPT_ANYNAME,
+ "Found anyName/except//anyName forbidden construct\n",
+ NULL, NULL);
+ } else if (ctxt->flags & XML_RELAXNG_IN_NSEXCEPT) {
+ xmlRngPErr(ctxt, cur,
+ XML_RNGP_PAT_NSNAME_EXCEPT_ANYNAME,
+ "Found nsName/except//anyName forbidden construct\n",
+ NULL, NULL);
+ }
+ }
+ /*
+ * Thisd is not an else since "include" is transformed
+ * into a div
+ */
+ if (xmlStrEqual(cur->name, BAD_CAST "div")) {
+ xmlChar *ns;
+ xmlNodePtr child, ins, tmp;
+
+ /*
+ * implements rule 4.11
+ */
+
+ ns = xmlGetProp(cur, BAD_CAST "ns");
+
+ child = cur->children;
+ ins = cur;
+ while (child != NULL) {
+ if (ns != NULL) {
+ if (!xmlHasProp(child, BAD_CAST "ns")) {
+ xmlSetProp(child, BAD_CAST "ns", ns);
+ }
+ }
+ tmp = child->next;
+ xmlUnlinkNode(child);
+ ins = xmlAddNextSibling(ins, child);
+ child = tmp;
+ }
+ if (ns != NULL)
+ xmlFree(ns);
+ /*
+ * Since we are about to delete cur, if it's nsDef is non-NULL we
+ * need to preserve it (it contains the ns definitions for the
+ * children we just moved). We'll just stick it on to the end
+ * of cur->parent's list, since it's never going to be re-serialized
+ * (bug 143738).
+ */
+ if (cur->nsDef != NULL) {
+ xmlNsPtr parDef = (xmlNsPtr)&cur->parent->nsDef;
+ while (parDef->next != NULL)
+ parDef = parDef->next;
+ parDef->next = cur->nsDef;
+ cur->nsDef = NULL;
+ }
+ delete = cur;
+ goto skip_children;
+ }
+ }
+ }
+ /*
+ * Simplification 4.2 whitespaces
+ */
+ else if ((cur->type == XML_TEXT_NODE) ||
+ (cur->type == XML_CDATA_SECTION_NODE)) {
+ if (IS_BLANK_NODE(cur)) {
+ if (cur->parent->type == XML_ELEMENT_NODE) {
+ if ((!xmlStrEqual(cur->parent->name, BAD_CAST "value"))
+ &&
+ (!xmlStrEqual
+ (cur->parent->name, BAD_CAST "param")))
+ delete = cur;
+ } else {
+ delete = cur;
+ goto skip_children;
+ }
+ }
+ } else {
+ 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;
+ }
+}
+
+/**
+ * xmlRelaxNGCleanupDoc:
+ * @ctxt: a Relax-NG parser context
+ * @doc: an xmldocPtr document pointer
+ *
+ * Cleanup the document from unwanted nodes for parsing, resolve
+ * Include and externalRef lookups.
+ *
+ * Returns the cleaned up document or NULL in case of error
+ */
+static xmlDocPtr
+xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt, xmlDocPtr doc)
+{
+ xmlNodePtr root;
+
+ /*
+ * Extract the root
+ */
+ root = xmlDocGetRootElement(doc);
+ if (root == NULL) {
+ xmlRngPErr(ctxt, (xmlNodePtr) doc, XML_RNGP_EMPTY, "xmlRelaxNGParse: %s is empty\n",
+ ctxt->URL, NULL);
+ return (NULL);
+ }
+ xmlRelaxNGCleanupTree(ctxt, root);
+ return (doc);
+}
+
+/**
+ * xmlRelaxNGParse:
+ * @ctxt: a Relax-NG parser context
+ *
+ * parse a schema definition resource and build an internal
+ * XML Shema struture which can be used to validate instances.
+ *
+ * Returns the internal XML RelaxNG structure built from the resource or
+ * NULL in case of error
+ */
+xmlRelaxNGPtr
+xmlRelaxNGParse(xmlRelaxNGParserCtxtPtr ctxt)
+{
+ xmlRelaxNGPtr ret = NULL;
+ xmlDocPtr doc;
+ xmlNodePtr root;
+
+ xmlRelaxNGInitTypes();
+
+ if (ctxt == NULL)
+ return (NULL);
+
+ /*
+ * First step is to parse the input document into an DOM/Infoset
+ */
+ if (ctxt->URL != NULL) {
+ doc = xmlReadFile((const char *) ctxt->URL,NULL,0);
+ if (doc == NULL) {
+ xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,
+ "xmlRelaxNGParse: could not load %s\n", ctxt->URL,
+ NULL);
+ return (NULL);
+ }
+ } else if (ctxt->buffer != NULL) {
+ doc = xmlReadMemory(ctxt->buffer, ctxt->size,NULL,NULL,0);
+ if (doc == NULL) {
+ xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR,
+ "xmlRelaxNGParse: could not parse schemas\n", NULL,
+ NULL);
+ return (NULL);
+ }
+ doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
+ ctxt->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
+ } else if (ctxt->document != NULL) {
+ doc = ctxt->document;
+ } else {
+ xmlRngPErr(ctxt, NULL, XML_RNGP_EMPTY,
+ "xmlRelaxNGParse: nothing to parse\n", NULL, NULL);
+ return (NULL);
+ }
+ ctxt->document = doc;
+
+ /*
+ * Some preprocessing of the document content
+ */
+ doc = xmlRelaxNGCleanupDoc(ctxt, doc);
+ if (doc == NULL) {
+ xmlFreeDoc(ctxt->document);
+ ctxt->document = NULL;
+ return (NULL);
+ }
+
+ /*
+ * Then do the parsing for good
+ */
+ root = xmlDocGetRootElement(doc);
+ if (root == NULL) {
+ xmlRngPErr(ctxt, (xmlNodePtr) doc,
+ XML_RNGP_EMPTY, "xmlRelaxNGParse: %s is empty\n",
+ (ctxt->URL ? ctxt->URL : BAD_CAST "schemas"), NULL);
+
+ xmlFreeDoc(ctxt->document);
+ ctxt->document = NULL;
+ return (NULL);
+ }
+ ret = xmlRelaxNGParseDocument(ctxt, root);
+ if (ret == NULL) {
+ xmlFreeDoc(ctxt->document);
+ ctxt->document = NULL;
+ return (NULL);
+ }
+
+ /*
+ * Check the ref/defines links
+ */
+ /*
+ * try to preprocess interleaves
+ */
+ if (ctxt->interleaves != NULL) {
+ xmlHashScan(ctxt->interleaves,
+ (xmlHashScanner) xmlRelaxNGComputeInterleaves, ctxt);
+ }
+
+ /*
+ * if there was a parsing error return NULL
+ */
+ if (ctxt->nbErrors > 0) {
+ xmlRelaxNGFree(ret);
+ ctxt->document = NULL;
+ xmlFreeDoc(doc);
+ return (NULL);
+ }
+
+ /*
+ * try to compile (parts of) the schemas
+ */
+ if ((ret->topgrammar != NULL) && (ret->topgrammar->start != NULL)) {
+ if (ret->topgrammar->start->type != XML_RELAXNG_START) {
+ xmlRelaxNGDefinePtr def;
+
+ def = xmlRelaxNGNewDefine(ctxt, NULL);
+ if (def != NULL) {
+ def->type = XML_RELAXNG_START;
+ def->content = ret->topgrammar->start;
+ ret->topgrammar->start = def;
+ }
+ }
+ xmlRelaxNGTryCompile(ctxt, ret->topgrammar->start);
+ }
+
+ /*
+ * Transfer the pointer for cleanup at the schema level.
+ */
+ ret->doc = doc;
+ ctxt->document = NULL;
+ ret->documents = ctxt->documents;
+ ctxt->documents = NULL;
+
+ ret->includes = ctxt->includes;
+ ctxt->includes = NULL;
+ ret->defNr = ctxt->defNr;
+ ret->defTab = ctxt->defTab;
+ ctxt->defTab = NULL;
+ if (ctxt->idref == 1)
+ ret->idref = 1;
+
+ return (ret);
+}
+
+/**
+ * xmlRelaxNGSetParserErrors:
+ * @ctxt: a Relax-NG 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
+xmlRelaxNGSetParserErrors(xmlRelaxNGParserCtxtPtr ctxt,
+ xmlRelaxNGValidityErrorFunc err,
+ xmlRelaxNGValidityWarningFunc warn, void *ctx)
+{
+ if (ctxt == NULL)
+ return;
+ ctxt->error = err;
+ ctxt->warning = warn;
+ ctxt->serror = NULL;
+ ctxt->userData = ctx;
+}
+
+/**
+ * xmlRelaxNGGetParserErrors:
+ * @ctxt: a Relax-NG validation 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 validation context
+ *
+ * Returns -1 in case of failure, 0 otherwise.
+ */
+int
+xmlRelaxNGGetParserErrors(xmlRelaxNGParserCtxtPtr 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);
+}
+
+/**
+ * xmlRelaxNGSetParserStructuredErrors:
+ * @ctxt: a Relax-NG parser context
+ * @serror: the error callback
+ * @ctx: contextual data for the callbacks
+ *
+ * Set the callback functions used to handle errors for a parsing context
+ */
+void
+xmlRelaxNGSetParserStructuredErrors(xmlRelaxNGParserCtxtPtr ctxt,
+ xmlStructuredErrorFunc serror,
+ void *ctx)
+{
+ if (ctxt == NULL)
+ return;
+ ctxt->serror = serror;
+ ctxt->error = NULL;
+ ctxt->warning = NULL;
+ ctxt->userData = ctx;
+}
+
+#ifdef LIBXML_OUTPUT_ENABLED
+
+/************************************************************************
+ * *
+ * Dump back a compiled form *
+ * *
+ ************************************************************************/
+static void xmlRelaxNGDumpDefine(FILE * output,
+ xmlRelaxNGDefinePtr define);
+
+/**
+ * xmlRelaxNGDumpDefines:
+ * @output: the file output
+ * @defines: a list of define structures
+ *
+ * Dump a RelaxNG structure back
+ */
+static void
+xmlRelaxNGDumpDefines(FILE * output, xmlRelaxNGDefinePtr defines)
+{
+ while (defines != NULL) {
+ xmlRelaxNGDumpDefine(output, defines);
+ defines = defines->next;
+ }
+}
+
+/**
+ * xmlRelaxNGDumpDefine:
+ * @output: the file output
+ * @define: a define structure
+ *
+ * Dump a RelaxNG structure back
+ */
+static void
+xmlRelaxNGDumpDefine(FILE * output, xmlRelaxNGDefinePtr define)
+{
+ if (define == NULL)
+ return;
+ switch (define->type) {
+ case XML_RELAXNG_EMPTY:
+ fprintf(output, "<empty/>\n");
+ break;
+ case XML_RELAXNG_NOT_ALLOWED:
+ fprintf(output, "<notAllowed/>\n");
+ break;
+ case XML_RELAXNG_TEXT:
+ fprintf(output, "<text/>\n");
+ break;
+ case XML_RELAXNG_ELEMENT:
+ fprintf(output, "<element>\n");
+ if (define->name != NULL) {
+ fprintf(output, "<name");
+ if (define->ns != NULL)
+ fprintf(output, " ns=\"%s\"", define->ns);
+ fprintf(output, ">%s</name>\n", define->name);
+ }
+ xmlRelaxNGDumpDefines(output, define->attrs);
+ xmlRelaxNGDumpDefines(output, define->content);
+ fprintf(output, "</element>\n");
+ break;
+ case XML_RELAXNG_LIST:
+ fprintf(output, "<list>\n");
+ xmlRelaxNGDumpDefines(output, define->content);
+ fprintf(output, "</list>\n");
+ break;
+ case XML_RELAXNG_ONEORMORE:
+ fprintf(output, "<oneOrMore>\n");
+ xmlRelaxNGDumpDefines(output, define->content);
+ fprintf(output, "</oneOrMore>\n");
+ break;
+ case XML_RELAXNG_ZEROORMORE:
+ fprintf(output, "<zeroOrMore>\n");
+ xmlRelaxNGDumpDefines(output, define->content);
+ fprintf(output, "</zeroOrMore>\n");
+ break;
+ case XML_RELAXNG_CHOICE:
+ fprintf(output, "<choice>\n");
+ xmlRelaxNGDumpDefines(output, define->content);
+ fprintf(output, "</choice>\n");
+ break;
+ case XML_RELAXNG_GROUP:
+ fprintf(output, "<group>\n");
+ xmlRelaxNGDumpDefines(output, define->content);
+ fprintf(output, "</group>\n");
+ break;
+ case XML_RELAXNG_INTERLEAVE:
+ fprintf(output, "<interleave>\n");
+ xmlRelaxNGDumpDefines(output, define->content);
+ fprintf(output, "</interleave>\n");
+ break;
+ case XML_RELAXNG_OPTIONAL:
+ fprintf(output, "<optional>\n");
+ xmlRelaxNGDumpDefines(output, define->content);
+ fprintf(output, "</optional>\n");
+ break;
+ case XML_RELAXNG_ATTRIBUTE:
+ fprintf(output, "<attribute>\n");
+ xmlRelaxNGDumpDefines(output, define->content);
+ fprintf(output, "</attribute>\n");
+ break;
+ case XML_RELAXNG_DEF:
+ fprintf(output, "<define");
+ if (define->name != NULL)
+ fprintf(output, " name=\"%s\"", define->name);
+ fprintf(output, ">\n");
+ xmlRelaxNGDumpDefines(output, define->content);
+ fprintf(output, "</define>\n");
+ break;
+ case XML_RELAXNG_REF:
+ fprintf(output, "<ref");
+ if (define->name != NULL)
+ fprintf(output, " name=\"%s\"", define->name);
+ fprintf(output, ">\n");
+ xmlRelaxNGDumpDefines(output, define->content);
+ fprintf(output, "</ref>\n");
+ break;
+ case XML_RELAXNG_PARENTREF:
+ fprintf(output, "<parentRef");
+ if (define->name != NULL)
+ fprintf(output, " name=\"%s\"", define->name);
+ fprintf(output, ">\n");
+ xmlRelaxNGDumpDefines(output, define->content);
+ fprintf(output, "</parentRef>\n");
+ break;
+ case XML_RELAXNG_EXTERNALREF:
+ fprintf(output, "<externalRef>");
+ xmlRelaxNGDumpDefines(output, define->content);
+ fprintf(output, "</externalRef>\n");
+ break;
+ case XML_RELAXNG_DATATYPE:
+ case XML_RELAXNG_VALUE:
+ TODO break;
+ case XML_RELAXNG_START:
+ case XML_RELAXNG_EXCEPT:
+ case XML_RELAXNG_PARAM:
+ TODO break;
+ case XML_RELAXNG_NOOP:
+ xmlRelaxNGDumpDefines(output, define->content);
+ break;
+ }
+}
+
+/**
+ * xmlRelaxNGDumpGrammar:
+ * @output: the file output
+ * @grammar: a grammar structure
+ * @top: is this a top grammar
+ *
+ * Dump a RelaxNG structure back
+ */
+static void
+xmlRelaxNGDumpGrammar(FILE * output, xmlRelaxNGGrammarPtr grammar, int top)
+{
+ if (grammar == NULL)
+ return;
+
+ fprintf(output, "<grammar");
+ if (top)
+ fprintf(output, " xmlns=\"http://relaxng.org/ns/structure/1.0\"");
+ switch (grammar->combine) {
+ case XML_RELAXNG_COMBINE_UNDEFINED:
+ break;
+ case XML_RELAXNG_COMBINE_CHOICE:
+ fprintf(output, " combine=\"choice\"");
+ break;
+ case XML_RELAXNG_COMBINE_INTERLEAVE:
+ fprintf(output, " combine=\"interleave\"");
+ break;
+ default:
+ fprintf(output, " <!-- invalid combine value -->");
+ }
+ fprintf(output, ">\n");
+ if (grammar->start == NULL) {
+ fprintf(output, " <!-- grammar had no start -->");
+ } else {
+ fprintf(output, "<start>\n");
+ xmlRelaxNGDumpDefine(output, grammar->start);
+ fprintf(output, "</start>\n");
+ }
+ /* TODO ? Dump the defines ? */
+ fprintf(output, "</grammar>\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 <mixed> 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 <libxml/xmlversion.h>
+#include <libxml/hash.h>
+#include <libxml/xmlstring.h>
+
+#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 <libxml/xmlversion.h>
+
+#ifdef LIBXML_SCHEMAS_ENABLED
+
+#include <libxml/xmlregexp.h>
+#include <libxml/hash.h>
+#include <libxml/dict.h>
+
+#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
+ * <schema> 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 <daniel@veillard.com>
+ */
+
+/*
+ * 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 <string.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/uri.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/pattern.h>
+#include <libxml/schematron.h>
+
+#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 <libxml/xmlversion.h>
+
+#ifdef LIBXML_SCHEMATRON_ENABLED
+
+#include <libxml/tree.h>
+
+#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 <Gary.Pennington@uk.sun.com>
+ * daniel@veillard.com
+ */
+
+#define IN_LIBXML
+#include "libxml.h"
+
+#include <string.h>
+
+#include <libxml/threads.h>
+#include <libxml/globals.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+
+#ifdef HAVE_WIN32_THREADS
+#include <windows.h>
+#ifndef HAVE_COMPILER_TLS
+#include <process.h>
+#endif
+#endif
+
+#ifdef HAVE_BEOS_THREADS
+#include <OS.h>
+#include <TLS.h>
+#endif
+
+#if defined(SOLARIS)
+#include <note.h>
+#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 <libxml/xmlversion.h>
+
+#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 <libxml/globals.h>
+#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 <string.h> /* for memset() only ! */
+
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_ZLIB_H
+#include <zlib.h>
+#endif
+
+#include <libxml/xmlmemory.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/uri.h>
+#include <libxml/entities.h>
+#include <libxml/valid.h>
+#include <libxml/xmlerror.h>
+#include <libxml/parserInternals.h>
+#include <libxml/globals.h>
+#ifdef LIBXML_HTML_ENABLED
+#include <libxml/HTMLtree.h>
+#endif
+#ifdef LIBXML_DEBUG_ENABLED
+#include <libxml/debugXML.h>
+#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 <libxml/hash.h>
+
+#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 "&quot;", 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 <stdio.h>
+#include <libxml/xmlversion.h>
+#include <libxml/xmlstring.h>
+
+#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 <libxml/xmlregexp.h>
+#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 <!DOCTYPE ... There is actually one for
+ * the internal subset and for the external subset.
+ */
+typedef struct _xmlDtd xmlDtd;
+typedef xmlDtd *xmlDtdPtr;
+struct _xmlDtd {
+ void *_private; /* application data */
+ xmlElementType type; /* XML_DTD_NODE, must be second ! */
+ const xmlChar *name; /* Name of the DTD */
+ struct _xmlNode *children; /* the value of the property link */
+ struct _xmlNode *last; /* last child link */
+ struct _xmlDoc *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 */
+ 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 <libxml/xmlmemory.h>
+#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 <string.h>
+
+#include <libxml/xmlmemory.h>
+#include <libxml/uri.h>
+#include <libxml/globals.h>
+#include <libxml/xmlerror.h>
+
+/************************************************************************
+ * *
+ * 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 "<segment>/../", where <segment> 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 "<segment>/..", where <segment>
+ * is a complete path segment not equal to "..", that
+ * "<segment>/.." 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 <libxml/xmlversion.h>
+#include <libxml/tree.h>
+
+#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 <string.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <libxml/xmlmemory.h>
+#include <libxml/hash.h>
+#include <libxml/uri.h>
+#include <libxml/valid.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/xmlerror.h>
+#include <libxml/list.h>
+#include <libxml/globals.h>
+
+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, "<!ELEMENT ");
+ if (elem->prefix != NULL) {
+ xmlBufferWriteCHAR(buf, elem->prefix);
+ xmlBufferWriteChar(buf, ":");
+ }
+ xmlBufferWriteCHAR(buf, elem->name);
+ xmlBufferWriteChar(buf, " EMPTY>\n");
+ break;
+ case XML_ELEMENT_TYPE_ANY:
+ xmlBufferWriteChar(buf, "<!ELEMENT ");
+ if (elem->prefix != NULL) {
+ xmlBufferWriteCHAR(buf, elem->prefix);
+ xmlBufferWriteChar(buf, ":");
+ }
+ xmlBufferWriteCHAR(buf, elem->name);
+ xmlBufferWriteChar(buf, " ANY>\n");
+ break;
+ case XML_ELEMENT_TYPE_MIXED:
+ xmlBufferWriteChar(buf, "<!ELEMENT ");
+ if (elem->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, "<!ELEMENT ");
+ if (elem->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, "<!ATTLIST ");
+ xmlBufferWriteCHAR(buf, attr->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, "<!NOTATION ");
+ xmlBufferWriteCHAR(buf, nota->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 <empty> </empty> 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 "<!dummy?>", 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 <libxml/xmlversion.h>
+#include <libxml/xmlerror.h>
+#include <libxml/tree.h>
+#include <libxml/list.h>
+#include <libxml/xmlautomata.h>
+#include <libxml/xmlregexp.h>
+
+#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 <string.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/uri.h>
+#include <libxml/xpointer.h>
+#include <libxml/parserInternals.h>
+#include <libxml/xmlerror.h>
+#include <libxml/encoding.h>
+#include <libxml/globals.h>
+
+#ifdef LIBXML_XINCLUDE_ENABLED
+#include <libxml/xinclude.h>
+
+
+#define XINCLUDE_MAX_DEPTH 40
+
+/* #define DEBUG_XINCLUDE */
+#ifdef DEBUG_XINCLUDE
+#ifdef LIBXML_DEBUG_ENABLED
+#include <libxml/debugXML.h>
+#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 <libxml/xmlversion.h>
+#include <libxml/tree.h>
+
+#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 <string.h> /* for memset() only */
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_ZLIB_H
+#include <zlib.h>
+#endif
+
+#include <libxml/xmlmemory.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/valid.h>
+#include <libxml/xlink.h>
+#include <libxml/globals.h>
+
+#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 <libxml/xmlversion.h>
+#include <libxml/tree.h>
+
+#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 <string.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_ZLIB_H
+#include <zlib.h>
+#endif
+
+#ifdef WIN32
+#include <windows.h>
+#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 <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/xmlIO.h>
+#include <libxml/uri.h>
+#include <libxml/nanohttp.h>
+#include <libxml/nanoftp.h>
+#include <libxml/xmlerror.h>
+#ifdef LIBXML_CATALOG_ENABLED
+#include <libxml/catalog.h>
+#endif
+#include <libxml/globals.h>
+
+/* #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 <stdio.h>
+#include <libxml/xmlversion.h>
+
+#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 <libxml/globals.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/encoding.h>
+
+#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 <libxml/xmlversion.h>
+#include <libxml/tree.h>
+
+#ifdef LIBXML_REGEXP_ENABLED
+#ifdef LIBXML_AUTOMATA_ENABLED
+#include <libxml/xmlregexp.h>
+
+#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 <libxml/parser.h>
+
+#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 <igor@zlatkovic.com>
+ */
+
+#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 <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#else
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#endif
+
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#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 <libxml/globals.h> /* must come before xmlmemory.h */
+#include <libxml/xmlmemory.h>
+#include <libxml/xmlerror.h>
+#include <libxml/threads.h>
+
+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(&currentTime);
+ 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 <stdio.h>
+#include <libxml/xmlversion.h>
+
+/**
+ * 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 <libxml/threads.h>
+#include <libxml/globals.h>
+#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 <string.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/xmlerror.h>
+#include <libxml/xmlmodule.h>
+#include <libxml/globals.h>
+
+#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 <dlfcn.h>
+#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 <dl.h>
+#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 <windows.h>
+
+/*
+ * 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 <kernel/image.h>
+
+/*
+ * 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 <os2.h>
+
+/*
+ * 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 <libxml/xmlversion.h>
+
+#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 <string.h> /* for memset() only ! */
+#include <stdarg.h>
+
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <libxml/xmlmemory.h>
+#include <libxml/xmlIO.h>
+#include <libxml/xmlreader.h>
+#include <libxml/parserInternals.h>
+#ifdef LIBXML_SCHEMAS_ENABLED
+#include <libxml/relaxng.h>
+#include <libxml/xmlschemas.h>
+#endif
+#include <libxml/uri.h>
+#ifdef LIBXML_XINCLUDE_ENABLED
+#include <libxml/xinclude.h>
+#endif
+#ifdef LIBXML_PATTERN_ENABLED
+#include <libxml/pattern.h>
+#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 &#0; 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 <libxml/xmlversion.h>
+#include <libxml/tree.h>
+#include <libxml/xmlIO.h>
+#ifdef LIBXML_SCHEMAS_ENABLED
+#include <libxml/relaxng.h>
+#include <libxml/xmlschemas.h>
+#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 <veillard@redhat.com>
+ */
+
+#define IN_LIBXML
+#include "libxml.h"
+
+#ifdef LIBXML_REGEXP_ENABLED
+
+/* #define DEBUG_ERR */
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#include <libxml/tree.h>
+#include <libxml/parserInternals.h>
+#include <libxml/xmlregexp.h>
+#include <libxml/xmlautomata.h>
+#include <libxml/xmlunicode.h>
+
+#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 <libxml/xmlversion.h>
+
+#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 <libxml/tree.h>
+#include <libxml/dict.h>
+#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 <string.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parserInternals.h>
+#include <libxml/tree.h>
+#include <libxml/xmlsave.h>
+
+#define MAX_INDENT 60
+
+#include <libxml/HTMLtree.h>
+
+/************************************************************************
+ * *
+ * 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, "<!DOCTYPE ");
+ xmlOutputBufferWriteString(buf, (const char *)dtd->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, "<?");
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ if (cur->content != NULL) {
+ xmlOutputBufferWrite(buf, 1, " ");
+ xmlOutputBufferWriteString(buf, (const char *)cur->content);
+ }
+ xmlOutputBufferWrite(buf, 2, "?>");
+ } else {
+ xmlOutputBufferWrite(buf, 2, "<?");
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ xmlOutputBufferWrite(buf, 2, "?>");
+ }
+ return;
+ }
+ if (cur->type == XML_COMMENT_NODE) {
+ if (cur->content != NULL) {
+ xmlOutputBufferWrite(buf, 4, "<!--");
+ xmlOutputBufferWriteString(buf, (const char *)cur->content);
+ xmlOutputBufferWrite(buf, 3, "-->");
+ }
+ 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, "<![CDATA[]]>");
+ } else {
+ start = end = cur->content;
+ while (*end != '\0') {
+ if ((*end == ']') && (*(end + 1) == ']') &&
+ (*(end + 2) == '>')) {
+ end = end + 2;
+ xmlOutputBufferWrite(buf, 9, "<![CDATA[");
+ xmlOutputBufferWrite(buf, end - start, (const char *)start);
+ xmlOutputBufferWrite(buf, 3, "]]>");
+ start = end;
+ }
+ end++;
+ }
+ if (start != end) {
+ xmlOutputBufferWrite(buf, 9, "<![CDATA[");
+ xmlOutputBufferWriteString(buf, (const char *)start);
+ xmlOutputBufferWrite(buf, 3, "]]>");
+ }
+ }
+ 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, "</");
+ 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, 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, "<?xml version=");
+ if (cur->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, "<?");
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ if (cur->content != NULL) {
+ xmlOutputBufferWrite(buf, 1, " ");
+ xmlOutputBufferWriteString(buf, (const char *)cur->content);
+ }
+ xmlOutputBufferWrite(buf, 2, "?>");
+ } else {
+ xmlOutputBufferWrite(buf, 2, "<?");
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ xmlOutputBufferWrite(buf, 2, "?>");
+ }
+ return;
+ }
+ if (cur->type == XML_COMMENT_NODE) {
+ if (cur->content != NULL) {
+ xmlOutputBufferWrite(buf, 4, "<!--");
+ xmlOutputBufferWriteString(buf, (const char *)cur->content);
+ xmlOutputBufferWrite(buf, 3, "-->");
+ }
+ 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, "<![CDATA[");
+ xmlOutputBufferWrite(buf, end - start, (const char *)start);
+ xmlOutputBufferWrite(buf, 3, "]]>");
+ start = end;
+ }
+ end++;
+ }
+ if (start != end) {
+ xmlOutputBufferWrite(buf, 9, "<![CDATA[");
+ xmlOutputBufferWriteString(buf, (const char *)start);
+ xmlOutputBufferWrite(buf, 3, "]]>");
+ }
+ 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,
+ "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=");
+ if (ctxt->encoding) {
+ xmlOutputBufferWriteString(buf, (const char *)ctxt->encoding);
+ } else {
+ xmlOutputBufferWrite(buf, 5, "UTF-8");
+ }
+ xmlOutputBufferWrite(buf, 4, "\" />");
+ if (ctxt->format)
+ xmlOutputBufferWrite(buf, 1, "\n");
+ } else {
+ xmlOutputBufferWrite(buf, 1, ">");
+ }
+ /*
+ * C.3. Element Minimization and Empty Element Content
+ */
+ xmlOutputBufferWrite(buf, 2, "</");
+ 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, 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,
+ "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=");
+ if (ctxt->encoding) {
+ xmlOutputBufferWriteString(buf, (const char *)ctxt->encoding);
+ } else {
+ xmlOutputBufferWrite(buf, 5, "UTF-8");
+ }
+ xmlOutputBufferWrite(buf, 4, "\" />");
+ }
+ 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, "<![CDATA[");
+ xmlOutputBufferWrite(buf, end - start,
+ (const char *)start);
+ xmlOutputBufferWrite(buf, 3, "]]>");
+ start = end;
+ }
+ end++;
+ }
+ if (start != end) {
+ xmlOutputBufferWrite(buf, 9, "<![CDATA[");
+ xmlOutputBufferWrite(buf, end - start,
+ (const char *)start);
+ xmlOutputBufferWrite(buf, 3, "]]>");
+ }
+ }
+ } 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, "</");
+ 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, 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 "&#10;", 5);
+ cur++;
+ base = cur;
+ } else if (*cur == '\r') {
+ if (base != cur)
+ xmlBufferAdd(buf, base, cur - base);
+ xmlBufferAdd(buf, BAD_CAST "&#13;", 5);
+ cur++;
+ base = cur;
+ } else if (*cur == '\t') {
+ if (base != cur)
+ xmlBufferAdd(buf, base, cur - base);
+ xmlBufferAdd(buf, BAD_CAST "&#9;", 4);
+ cur++;
+ base = cur;
+ } else if (*cur == '"') {
+ if (base != cur)
+ xmlBufferAdd(buf, base, cur - base);
+ xmlBufferAdd(buf, BAD_CAST "&quot;", 6);
+ cur++;
+ base = cur;
+ } else if (*cur == '<') {
+ if (base != cur)
+ xmlBufferAdd(buf, base, cur - base);
+ xmlBufferAdd(buf, BAD_CAST "&lt;", 4);
+ cur++;
+ base = cur;
+ } else if (*cur == '>') {
+ if (base != cur)
+ xmlBufferAdd(buf, base, cur - base);
+ xmlBufferAdd(buf, BAD_CAST "&gt;", 4);
+ cur++;
+ base = cur;
+ } else if (*cur == '&') {
+ if (base != cur)
+ xmlBufferAdd(buf, base, cur - base);
+ xmlBufferAdd(buf, BAD_CAST "&amp;", 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 <libxml/xmlversion.h>
+#include <libxml/tree.h>
+#include <libxml/encoding.h>
+#include <libxml/xmlIO.h>
+
+#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 <veillard@redhat.com>
+ */
+
+/*
+ * 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: <restriction>, <extension>,
+ * <simpleContent>, <complexContent>, <list>, <union>
+ *
+ * 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 <string.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/hash.h>
+#include <libxml/uri.h>
+#include <libxml/xmlschemas.h>
+#include <libxml/schemasInternals.h>
+#include <libxml/xmlschemastypes.h>
+#include <libxml/xmlautomata.h>
+#include <libxml/xmlregexp.h>
+#include <libxml/dict.h>
+#include <libxml/encoding.h>
+#include <libxml/xmlIO.h>
+#ifdef LIBXML_PATTERN_ENABLED
+#include <libxml/pattern.h>
+#endif
+#ifdef LIBXML_READER_ENABLED
+#include <libxml/xmlreader.h>
+#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 <list> and <union>.
+ */
+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 <import>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 <import>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 <any> 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 <attributeGroup>",
+ 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 <simpleType>,
+ * 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 <simpleType> must not both be present.
+ */
+ xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
+ NULL, node, child,
+ "The attribute 'type' and the <simpleType> 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 <simpleType> must not both be present.
+ */
+ xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
+ NULL, node, child,
+ "The attribute 'type' and the <simpleType> 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 <attributeGroup> 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
+ * <selector> and <field> 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 <selector>.
+ */
+ if (IS_SCHEMA(child, "selector")) {
+ item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
+ item, child, 0);
+ child = child->next;
+ /*
+ * Child elements <field>.
+ */
+ 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 <element> 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 <annotation> 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 <simpleType> or <complexType> are mutually
+ * exclusive
+ */
+ if (decl->namedType != NULL) {
+ xmlSchemaPContentErr(ctxt,
+ XML_SCHEMAP_SRC_ELEMENT_3,
+ NULL, node, child,
+ "The attribute 'type' and the <complexType> 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 <simpleType> or <complexType> are
+ * mutually exclusive
+ */
+ if (decl->namedType != NULL) {
+ xmlSchemaPContentErr(ctxt,
+ XML_SCHEMAP_SRC_ELEMENT_3,
+ NULL, node, child,
+ "The attribute 'type' and the <simpleType> 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 <list> or <union> 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 <union> 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 <simpleType> 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 <list> or <union> 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 <simpleType> [child] of
+ * the <list> 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 <simpleType> 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 <simpleType> 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 <simpleType> 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 <schema> 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 <simpleType> must have a
+ * <restriction> 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 "
+ "<simpleType> must have a <restriction> 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 <import> 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 <import> that comes with a location.
+ * Further <import>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 <schema> 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 {
+ /* <include> and <redefine> */
+ 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 <import>:
+ * 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 <schema> 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 <schema> 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 <schema>'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
+ * <schema> 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 <import>: "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 <include> and <redefine>.
+ */
+ 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 <include>:
+ * 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 <annotation> 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 <group> 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 (<restriction> has no <simpleType> "
+ * 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 <simpleType> must have a
+ * <restriction> 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 <simpleType><restriction><simpleType>.
+ */
+ if (IS_SCHEMA(child, "simpleType")) {
+ if (type->base != NULL) {
+ /*
+ * src-restriction-base-or-simpleType
+ * Either the base [attribute] or the simpleType [child] of the
+ * <restriction> element must be present, but not both.
+ */
+ xmlSchemaPContentErr(ctxt,
+ XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
+ NULL, node, child,
+ "The attribute 'base' and the <simpleType> 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 <simpleType> child "
+ "must be present", NULL);
+ }
+ } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
+ /*
+ * Corresponds to <complexType><complexContent><restriction>...
+ * followed by:
+ *
+ * Model groups <all>, <choice> and <sequence>.
+ */
+ 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 <group>.
+ */
+ } 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 <complexType><simpleContent><restriction>...
+ *
+ * "1.1 the simple type definition corresponding to the <simpleType>
+ * among the [children] of <restriction> 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 <complexType><simpleContent><restriction>...
+ * <simpleType><restriction>...
+ */
+
+ /*
+ * 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 <extension>, which is found inside a
+ * <simpleContent> or <complexContent>.
+ * *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 <complexType><complexContent><extension>... and:
+ *
+ * Model groups <all>, <choice>, <sequence> and <group>.
+ */
+ 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")) {
+ /*
+ * <complexType><simpleContent>...
+ * 3.4.3 : 2.2
+ * Specifying mixed='true' when the <simpleContent>
+ * 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")) {
+ /*
+ * <complexType><complexContent>...
+ */
+ type->contentType = XML_SCHEMA_CONTENT_EMPTY;
+ xmlSchemaParseComplexContent(ctxt, schema, child,
+ &hasRestrictionOrExtension);
+ child = child->next;
+ } else {
+ /*
+ * E.g <complexType><sequence>... or <complexType><attribute>... etc.
+ *
+ * SPEC
+ * "...the third alternative (neither <simpleContent> nor
+ * <complexContent>) 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 "
+ "<complexType> must have a <restriction> or <extension> "
+ "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<<i) {
+ return (-1);
+ }
+ }
+ ctxt->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 <sequence>.
+ */
+ 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",
+ "<element> 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
+ * <all>.
+ */
+ 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 <union> 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
+ * <simpleType>s among the [children] of <union>, 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 <restriction> 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 {
+ /* <all> and <sequence> */
+ 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 {
+ /* <all> and <sequence> */
+ 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
+* <union> alternative is chosen, there must not be any entries in the
+* memberTypes [attribute] at any depth which resolve to the component
+* corresponding to the <simpleType>."
+*
+* 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: <simpleType><list ..
+ */
+ /*
+ * 2.3.1
+ * 2.3.1.1 The {final} of the {item type definition} must not
+ * contain list.
+ */
+ if (xmlSchemaTypeFinalContains(itemType,
+ XML_SCHEMAS_TYPE_FINAL_LIST)) {
+ xmlSchemaPCustomErr(pctxt,
+ XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
+ WXS_BASIC_CAST type, NULL,
+ "The final of its item type '%s' must not contain 'list'",
+ xmlSchemaGetComponentQName(&str, itemType));
+ FREE_AND_NULL(str)
+ return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
+ }
+ /*
+ * 2.3.1.2 The {facets} must only contain the whiteSpace
+ * facet component.
+ * OPTIMIZE TODO: the S4S already disallows any facet
+ * to be specified.
+ */
+ if (type->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: <simpleType><restriction ...
+ * I.e. the variety of "list" is inherited.
+ */
+ /*
+ * 2.3.2
+ * 2.3.2.1 The {base type definition} must have a {variety} of list.
+ */
+ if (! WXS_IS_LIST(type->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 <restriction> alternative is chosen,
+ * either it must have a base [attribute] or a <simpleType> among its
+ * [children], but not both."
+ * NOTE: This is checked in the parse function of <restriction>.
+ */
+ /*
+ *
+ */
+ } else if (WXS_IS_LIST(type)) {
+ /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
+ * an itemType [attribute] or a <simpleType> among its [children],
+ * but not both."
+ *
+ * NOTE: This is checked in the parse function of <list>.
+ */
+ } 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 <complexContent> 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 <complexContent>, 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 <simpleContent> 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 <extension> 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 <simpleContent> and <restriction>, 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 <restriction> 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 <simpleType> 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 <simpleType> among the [children] of
+ * <restriction>.
+ */
+ /* TODO: Change error code to ..._SRC_CT_2_2. */
+ xmlSchemaPCustomErr(ctxt,
+ XML_SCHEMAP_SRC_CT_1,
+ WXS_BASIC_CAST type, NULL,
+ "A <simpleType> is expected among the children "
+ "of <restriction>, if <simpleContent> 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 <simpleContent> and <restriction> 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 <simpleContent> and <extension> 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 <all> or <sequence> model group particle
+ * @b: the base <all> or <sequence> 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 <simpleType><list>...
+ */
+ 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 <simpleType><union>...
+ */
+ 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 <simpleType><restriction>...
+ */
+ 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 <restriction> 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 <complexType><simpleContent>...
+ */
+ 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 <restriction> + base type is <complexType>,
+ * "whose own {content type} is a simple type..."
+ */
+ if (type->contentTypeDef != NULL) {
+ /*
+ * SPEC (1.1) "the simple type definition corresponding to the
+ * <simpleType> among the [children] of <restriction> if there
+ * is one;"
+ * Note that this "<simpleType> among the [children]" was put
+ * into ->contentTypeDef during parsing.
+ */
+ contentBase = type->contentTypeDef;
+ type->contentTypeDef = NULL;
+ } else {
+ /*
+ * (1.2) "...otherwise (<restriction> has no <simpleType>
+ * 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 <complexType>
+ * 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 <restriction> + base is a mixed <complexType> with
+ * an emptiable particle, then a simple type definition which
+ * restricts the <restriction>'s <simpleType> 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 <simpleContent><restriction> "
+ "is missing a <simpleType> 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 <extension> + base is <complexType> with
+ * <simpleType> 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 <extension>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) <extension> + base is <simpleType>
+ * "... 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 <simpleContent>: unhandled "
+ "derivation case", type->name);
+ goto exit_failure;
+ }
+ } else {
+ int dummySequence = 0;
+ xmlSchemaParticlePtr particle =
+ (xmlSchemaParticlePtr) type->subtypes;
+ /*
+ * Corresponds to <complexType><complexContent>...
+ *
+ * NOTE that the effective mixed was already set during parsing of
+ * <complexType> and <complexContent>; 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 <complexType> 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
+ * <all>, <choice>, <group> or <sequence> among the
+ * [children]."
+ */
+ type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
+ }
+ /*
+ * Compute the "content type".
+ */
+ if (WXS_IS_RESTRICTION(type)) {
+ /*
+ * SPEC (3.1) "If <restriction>..."
+ * (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 <extension>..."
+ */
+ 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
+ * <sequence> with minOccurs==maxOccurs==1.
+ * Just add the base types's content type.
+ * NOTE that, although we miss to add an intermediate
+ * <sequence>, 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 <redefine>.
+ * That is, unless this element information item's parent is
+ * <redefine>, then among the [children], if any, there must
+ * not be an <attributeGroup> with ref [attribute] which resolves
+ * to the component corresponding to this <attributeGroup>. Indirect
+ * circularity is also ruled out. That is, when QName resolution
+ * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
+ * any <attributeGroup>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 <attributeGroup>.
+ */
+ 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 <simpleType> 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 <redefine>d schema _document_ or the schema; the latter
+ * would include all imported and included sub-schemas of the
+ * <redefine>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
+ * <scope> 0 NULL
+ * <bar> 1 NULL
+ * <target/> 2 2 target
+ * <bar>
+ * </scope>
+ *
+ * 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<<i)
+ return (-1);
+ }
+ ctxt->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 <libxml/xmlversion.h>
+
+#ifdef LIBXML_SCHEMAS_ENABLED
+
+#include <libxml/tree.h>
+
+#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 <veillard@redhat.com>
+ */
+
+#define IN_LIBXML
+#include "libxml.h"
+
+#ifdef LIBXML_SCHEMAS_ENABLED
+
+#include <string.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/hash.h>
+#include <libxml/valid.h>
+#include <libxml/xpath.h>
+#include <libxml/uri.h>
+
+#include <libxml/xmlschemas.h>
+#include <libxml/schemasInternals.h>
+#include <libxml/xmlschemastypes.h>
+
+#ifdef HAVE_MATH_H
+#include <math.h>
+#endif
+#ifdef HAVE_FLOAT_H
+#include <float.h>
+#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 <libxml/xmlversion.h>
+
+#ifdef LIBXML_SCHEMAS_ENABLED
+
+#include <libxml/schemasInternals.h>
+#include <libxml/xmlschemas.h>
+
+#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 <wbrack@mmm.com.hk>
+ *
+ * daniel@veillard.com
+ */
+
+#define IN_LIBXML
+#include "libxml.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parserInternals.h>
+#include <libxml/xmlstring.h>
+
+/************************************************************************
+ * *
+ * 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 <stdarg.h>
+#include <libxml/xmlversion.h>
+
+#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 <veillard@redhat.com>
+ */
+
+#define IN_LIBXML
+#include "libxml.h"
+
+#ifdef LIBXML_UNICODE_ENABLED
+
+#include <string.h>
+#include <libxml/xmlversion.h>
+#include <libxml/xmlunicode.h>
+#include <libxml/chvalid.h>
+
+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 <libxml/xmlversion.h>
+
+#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 <libxml/xmlexports.h>
+
+#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 <ansidecl.h>
+#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 <string.h>
+
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/uri.h>
+#include <libxml/HTMLtree.h>
+
+#ifdef LIBXML_WRITER_ENABLED
+
+#include <libxml/xmlwriter.h>
+
+#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, "<?xml version=");
+ if (count < 0)
+ return -1;
+ sum += count;
+ count = xmlOutputBufferWrite(writer->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;
+
+ return sum;
+}
+
+/**
+ * xmlTextWriterEndComment:
+ * @writer: the xmlTextWriterPtr
+ *
+ * End the current xml coment.
+ *
+ * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
+ */
+int
+xmlTextWriterEndComment(xmlTextWriterPtr writer)
+{
+ int count;
+ int sum;
+ xmlLinkPtr lk;
+ xmlTextWriterStackEntry *p;
+
+ if (writer == NULL) {
+ xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
+ "xmlTextWriterEndComment : invalid writer!\n");
+ return -1;
+ }
+
+ lk = xmlListFront(writer->nodes);
+ if (lk == 0) {
+ xmlWriterErrMsg(writer, XML_ERR_INTERNAL_ERROR,
+ "xmlTextWriterEndComment : not allowed in this context!\n");
+ return -1;
+ }
+
+ p = (xmlTextWriterStackEntry *) xmlLinkGetData(lk);
+ if (p == 0)
+ return -1;
+
+ sum = 0;
+ switch (p->state) {
+ case XML_TEXTWRITER_COMMENT:
+ 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, "</");
+ if (count < 0)
+ return -1;
+ sum += count;
+ count = xmlOutputBufferWriteString(writer->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, "</");
+ if (count < 0)
+ return -1;
+ sum += count;
+ count = xmlOutputBufferWriteString(writer->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, "<?");
+ if (count < 0)
+ return -1;
+ sum += count;
+ count =
+ xmlOutputBufferWriteString(writer->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, "<![CDATA[");
+ if (count < 0)
+ return -1;
+ sum += count;
+
+ return sum;
+}
+
+/**
+ * xmlTextWriterEndCDATA:
+ * @writer: the xmlTextWriterPtr
+ *
+ * End an xml CDATA section.
+ *
+ * Returns the bytes written (may be 0 because of buffering) or -1 in case of error
+ */
+int
+xmlTextWriterEndCDATA(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_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, "<!DOCTYPE ");
+ if (count < 0)
+ return -1;
+ sum += count;
+ count = xmlOutputBufferWriteString(writer->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, "<!ELEMENT ");
+ if (count < 0)
+ return -1;
+ sum += count;
+ count = xmlOutputBufferWriteString(writer->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, "<!ATTLIST ");
+ if (count < 0)
+ return -1;
+ sum += count;
+ count = xmlOutputBufferWriteString(writer->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, "<!ENTITY ");
+ if (count < 0)
+ return -1;
+ sum += count;
+
+ if (pe != 0) {
+ 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;
+
+ 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, "<!NOTATION ");
+ if (count < 0)
+ return -1;
+ sum += count;
+ count = xmlOutputBufferWriteString(writer->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 <alfred@mickautsch.de>
+ */
+
+#ifndef __XML_XMLWRITER_H__
+#define __XML_XMLWRITER_H__
+
+#include <libxml/xmlversion.h>
+
+#ifdef LIBXML_WRITER_ENABLED
+
+#include <stdarg.h>
+#include <libxml/xmlIO.h>
+#include <libxml/list.h>
+#include <libxml/xmlstring.h>
+
+#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 <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_MATH_H
+#include <math.h>
+#endif
+#ifdef HAVE_FLOAT_H
+#include <float.h>
+#endif
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#include <libxml/xmlmemory.h>
+#include <libxml/tree.h>
+#include <libxml/valid.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/parserInternals.h>
+#include <libxml/hash.h>
+#ifdef LIBXML_XPTR_ENABLED
+#include <libxml/xpointer.h>
+#endif
+#ifdef LIBXML_DEBUG_ENABLED
+#include <libxml/debugXML.h>
+#endif
+#include <libxml/xmlerror.h>
+#include <libxml/threads.h>
+#include <libxml/globals.h>
+#ifdef LIBXML_PATTERN_ENABLED
+#include <libxml/pattern.h>
+#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.
+ * <foo>
+ * <node2>
+ * <node1>Text-1(precedence1 == 2)</node1>
+ * </node2>
+ * Text-6(precedence2 == 3)
+ * </foo>
+ */
+ 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;i<ns->nodeNr;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; j<rloc->locNr; 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 <libxml/xmlversion.h>
+
+#ifdef LIBXML_XPATH_ENABLED
+
+#include <libxml/xmlerror.h>
+#include <libxml/tree.h>
+#include <libxml/hash.h>
+#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 <libxml/xmlversion.h>
+#include <libxml/xpath.h>
+
+#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 <string.h>
+#include <libxml/xpointer.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parserInternals.h>
+#include <libxml/uri.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/xmlerror.h>
+#include <libxml/globals.h>
+
+#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 <libxml/debugXML.h>
+#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 <libxml/xmlversion.h>
+
+#ifdef LIBXML_XPTR_ENABLED
+
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "localcharset.h"
+
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#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 <locale.h>
+#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 <unistd.h>
+# if HAVE_LANGINFO_CODESET
+# include <langinfo.h>
+# else
+# if 0 /* see comment below */
+# include <locale.h>
+# endif
+# endif
+# ifdef __CYGWIN__
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# endif
+#elif defined WINDOWS_NATIVE
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
+#if defined OS2
+# define INCL_DOS
+# include <os2.h>
+#endif
+
+/* For MB_CUR_MAX_L */
+#if defined DARWIN7
+# include <xlocale.h>
+#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 <http://www.gnu.org/licenses/>. */
+
+#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 <locale.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 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#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 <stddef.h>
+
+/* Mac OS X 10.5 defines the locale_t type in <xlocale.h>. */
+#if @HAVE_XLOCALE_H@
+# include <xlocale.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. */
+
+/* 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
+ <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_04> */
+
+ /* 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
+ <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_03> */
+
+ /* 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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Ulrich Drepper <drepper@gnu.org>, 1995. */
+/* Native Windows code written by Tor Lillqvist <tml@iki.fi>. */
+/* Mac OS X code written by Bruno Haible <bruno@clisp.org>. */
+
+#include <config.h>
+
+/* Specification. */
+#ifdef IN_LIBINTL
+# include "gettextP.h"
+#else
+# include "localename.h"
+#endif
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <locale.h>
+#include <string.h>
+
+#if HAVE_USELOCALE
+/* Mac OS X 10.5 defines the locale_t type in <xlocale.h>. */
+# if defined __APPLE__ && defined __MACH__
+# include <xlocale.h>
+# endif
+# include <langinfo.h>
+# if !defined IN_LIBINTL
+# include "glthread/lock.h"
+# endif
+#endif
+
+#if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE
+# include <CoreFoundation/CFString.h>
+# if HAVE_CFLOCALECOPYCURRENT
+# include <CoreFoundation/CFLocale.h>
+# elif HAVE_CFPREFERENCESCOPYAPPVALUE
+# include <CoreFoundation/CFPreferences.h>
+# 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 <windows.h>
+# include <winnls.h>
+/* 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 <goldsmit@apple.com> 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:
+ /* <http://www.microsoft.com/globaldev/reference/lcid-all.mspx> calls
+ it "Sepedi"; according to
+ <http://www.ethnologue.com/show_language.asp?code=nso>
+ <http://www.ethnologue.com/show_language.asp?code=sot>
+ 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 <http://sourceware.org/bugzilla/show_bug.cgi?id=10968>. */
+ 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 <libintl.h>),
+ 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 <http://www.gnu.org/licenses/>. */
+
+#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 <locale.h>,
+ 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 <locale.h>,
+ 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 <locale.h>,
+ 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 <http://www.gnu.org/licenses/>. */
+
+/* written by Jim Meyering */
+
+/* If the user's config.h happens to include <sys/stat.h>, let it include only
+ the system's <sys/stat.h> here, so that orig_lstat doesn't recurse to
+ rpl_lstat. */
+#define __need_system_sys_stat_h
+#include <config.h>
+
+#if !HAVE_LSTAT
+/* On systems that lack symlinks, our replacement <sys/stat.h> 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 <sys/types.h>
+# include <sys/stat.h>
+# 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 <sys/stat.h>, otherwise OSF/1 5.1 DTK cc
+ eliminates this include because of the preliminary #include <sys/stat.h>
+ above. */
+# include "sys/stat.h"
+
+# include <string.h>
+# include <errno.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+/* written by Jim Meyering and Bruno Haible */
+
+#define _GL_USE_STDLIB_ALLOC 1
+#include <config.h>
+/* 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 <stdlib.h>
+
+#include <errno.h>
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#define _GL_USE_STDLIB_ALLOC 1
+#include <config.h>
+
+/* Specification. */
+#include "malloca.h"
+
+#include <stdint.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _MALLOCA_H
+#define _MALLOCA_H
+
+#include <alloca.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+
+#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 <class type> struct sa_alignof_helper { char __slot1; type __slot2; };
+# define sa_alignof(type) offsetof (sa_alignof_helper<type>, __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 <http://www.gnu.org/licenses/>. */
+
+
+#include <config.h>
+
+#define MBCHAR_INLINE _GL_EXTERN_INLINE
+
+#include <limits.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>. */
+
+/* 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 <stdbool.h>
+#include <string.h>
+
+/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
+ <wchar.h>.
+ BSD/OS 4.1 has a bug: <stdio.h> and <time.h> must be included before
+ <wchar.h>. */
+#include <stdio.h>
+#include <time.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#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)
+
+/* <ctype.h>, <wctype.h> 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 <wchar.h> 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 <config.h>
+#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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>. */
+
+/* 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 <assert.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+
+/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
+ <wchar.h>.
+ BSD/OS 4.1 has a bug: <stdio.h> and <time.h> must be included before
+ <wchar.h>. */
+#include <stdio.h>
+#include <time.h>
+#include <wchar.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <wchar.h>
+
+#if GNULIB_defined_mbstate_t
+/* Implement mbrtowc() on top of mbtowc(). */
+
+# include <errno.h>
+# include <stdlib.h>
+
+# 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 <http://sourceware.org/bugzilla/show_bug.cgi?id=9674> */
+ 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <wchar.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <string.h>
+
+#include <stdlib.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include <wchar.h>
+
+/* 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 <http://lists.gnu.org/archive/html/bug-gnulib/2009-01/msg00329.html>.
+ 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <wchar.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <string.h>
+
+#include <stdbool.h>
+#include <stddef.h> /* 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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <haible@clisp.cons.org>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "mbswidth.h"
+
+/* Get MB_CUR_MAX. */
+#include <stdlib.h>
+
+#include <string.h>
+
+/* Get isprint(). */
+#include <ctype.h>
+
+/* Get mbstate_t, mbrtowc(), mbsinit(), wcwidth(). */
+#include <wchar.h>
+
+/* Get iswcntrl(). */
+#include <wctype.h>
+
+/* Get INT_MAX. */
+#include <limits.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include <stddef.h>
+
+/* Avoid a clash of our mbswidth() with a function of the same name defined
+ in UnixWare 7.1.1 <wchar.h>. We need this #include before the #define
+ below.
+ However, we don't want to #include <wchar.h> on all platforms because
+ - Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
+ <wchar.h>.
+ - BSD/OS 4.1 has a bug: <stdio.h> and <time.h> must be included before
+ <wchar.h>. */
+#if HAVE_DECL_MBSWIDTH_IN_WCHAR_H
+# include <wchar.h>
+#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 <config.h>
+#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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>. */
+
+/* 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 <assert.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
+ <wchar.h>.
+ BSD/OS 4.1 has a bug: <stdio.h> and <time.h> must be included before
+ <wchar.h>. */
+#include <stdio.h>
+#include <time.h>
+#include <wchar.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _LIBC
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include <stddef.h>
+
+#if defined _LIBC
+# include <memcopy.h>
+#else
+# define reg_char char
+#endif
+
+#include <limits.h>
+
+#if HAVE_BP_SYM_H || defined _LIBC
+# include <bp-sym.h>
+#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 <djm@gnu.ai.mit.edu>. */
+
+#include <config.h>
+
+#include <stddef.h>
+
+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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include <stddef.h>
+
+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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _MINMAX_H
+#define _MINMAX_H
+
+/* Note: MIN, MAX are also defined in <sys/param.h> 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 <limits.h> file
+ since otherwise we get redefinitions on some systems if <limits.h> is
+ included after this file. Likewise for <sys/param.h>.
+ 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 <limits.h>
+#elif HAVE_MINMAX_IN_SYS_PARAM_H
+# include <sys/param.h>
+#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 <http://www.gnu.org/licenses/>. */
+
+/* Extracted from misc/mkdtemp.c. */
+
+#include <config.h>
+
+/* Specification. */
+#include <stdlib.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+/* 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 <stdlib.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* 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 <stdlib.h>
+
+# 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 <windows.h>
+
+# 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 &not_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 = &not_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 <http://www.gnu.org/licenses/>. */
+
+#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
+ {
+ <Code that can trigger an invalid parameter notification
+ but does not do 'return', 'break', 'continue', nor 'goto'.>
+ }
+ CATCH_MSVC_INVAL
+ {
+ <Code that handles an invalid parameter notification
+ but does not do 'return', 'break', 'continue', nor 'goto'.>
+ }
+ 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 <excpt.h>
+
+/* Gnulib can define its own status codes, as described in the page
+ "Raising Software Exceptions" on microsoft.com
+ <http://msdn.microsoft.com/en-us/library/het71c37.aspx>.
+ 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
+ <http://msdn.microsoft.com/en-us/library/s58ftw19.aspx>.
+ 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 <setjmp.h>
+
+# 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "msvc-nothrow.h"
+
+/* Get declarations of the native Windows API functions. */
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#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 <io.h>
+
+# 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
+ <http://www.gnu.org/licenses/>. */
+
+
+#ifdef _LIBC
+# include <obstack.h>
+#else
+# include <config.h>
+# 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 <gnu-versions.h>
+# 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 <alignof.h>
+# define __alignof__(type) alignof_type (type)
+# endif
+# include <stdlib.h>
+# include <stdint.h>
+
+# 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 <stdio.h>
+
+/* 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 <libintl.h>
+# else
+# include "gettext.h"
+# endif
+# ifndef _
+# define _(msgid) gettext (msgid)
+# endif
+
+# ifdef _LIBC
+# include <libio/iolibio.h>
+# 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
+ <http://www.gnu.org/licenses/>. */
+
+/* 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 <stddef.h> /* For size_t and ptrdiff_t. */
+#include <string.h> /* 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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2007. */
+
+/* If the user's config.h happens to include <fcntl.h>, let it include only
+ the system's <fcntl.h> here, so that orig_open doesn't recurse to
+ rpl_open. */
+#define __need_system_fcntl_h
+#include <config.h>
+
+/* Get the original definition of open. It might be defined as a macro. */
+#include <fcntl.h>
+#include <sys/types.h>
+#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 <fcntl.h>, otherwise OSF/1 5.1 DTK cc eliminates
+ this include because of the preliminary #include <fcntl.h> above. */
+#include "fcntl.h"
+
+#include <errno.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#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 <http://www.opengroup.org/susv3/basedefs/xbd_chap04.html>
+ 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
+ <http://www.opengroup.org/susv3/functions/open.html> 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 <http://www.opengroup.org/susv3/basedefs/xbd_chap04.html>
+ 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <dirent.h>
+
+#include <errno.h>
+#include <stddef.h>
+
+#if HAVE_OPENDIR
+
+/* Override opendir(), to keep track of the open file descriptors.
+ Needed because there is a function dirfd(). */
+
+#else
+
+# include <stdlib.h>
+
+# include "dirent-private.h"
+# include "filename.h"
+
+#endif
+
+#if REPLACE_FCHDIR
+# include <unistd.h>
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _OSTREAM_H
+#define _OSTREAM_H
+
+#include <stddef.h>
+#include <string.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _OSTREAM_H
+#define _OSTREAM_H
+
+#include <stddef.h>
+#include <string.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#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.
+ <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html>
+ 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 <unistd.h>
+
+# include <limits.h>
+
+# 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 <sys/param.h>
+# 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",
+ <http://msdn.microsoft.com/en-us/library/aa365247(v=vs.85).aspx#maxpath>
+ 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 <stdio.h>,
+ - _MAX_PATH in <stdlib.h>,
+ - MAX_PATH in <windef.h>.
+ Undefine the original value, because mingw's <limits.h> 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#define PIPE_FILTER_AUX_INLINE _GL_EXTERN_INLINE
+
+#include "pipe-filter.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# include <windows.h>
+#else
+# include <signal.h>
+# include <sys/select.h>
+#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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include "pipe-filter.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# include <windows.h>
+#else
+# include <signal.h>
+# include <sys/select.h>
+#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
+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html>.
+ 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 <haible@clisp.cons.org>, 2009,
+ and Paolo Bonzini <bonzini@gnu.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _PIPE_FILTER_H
+#define _PIPE_FILTER_H
+
+#include <stdbool.h>
+#include <stddef.h>
+
+
+#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 <http://en.wikipedia.org/wiki/Generator_(computer_science)>.
+ 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 <http://en.wikipedia.org/wiki/Generator_(computer_science)>
+ and <http://en.wikipedia.org/wiki/Coroutine>.) 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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Jim Meyering. */
+
+#include <config.h>
+
+#include "unistd-safer.h"
+
+#include <unistd.h>
+#include <errno.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Eric Blake. */
+
+#include <config.h>
+
+/* Specification. */
+#include "unistd-safer.h"
+
+#include <unistd.h>
+#include <errno.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <unistd.h>
+
+#include <errno.h>
+#include <fcntl.h>
+
+#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 <io.h>
+
+#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 <http://www.opengroup.org/onlinepubs/9699919799/functions/pipe.html>
+ 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 <http://www.gnu.org/licenses/>. */
+
+/* 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 <config.h>
+#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 <http://www.gnu.org/licenses/>. */
+
+#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 <stddef.h>
+
+/* Get wchar_t. */
+#if HAVE_WCHAR_T
+# include <stddef.h>
+#endif
+
+/* Get wint_t. */
+#if HAVE_WINT_T
+# include <wchar.h>
+#endif
+
+/* Get va_list. */
+#include <stdarg.h>
+
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+/* 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 <config.h>
+#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 <stddef.h>
+
+/* Get intmax_t. */
+#if defined IN_LIBINTL || defined IN_LIBASPRINTF
+# if HAVE_STDINT_H_WITH_UINTMAX
+# include <stdint.h>
+# endif
+# if HAVE_INTTYPES_H_WITH_UINTMAX
+# include <inttypes.h>
+# endif
+#else
+# include <stdint.h>
+#endif
+
+/* malloc(), realloc(), free(). */
+#include <stdlib.h>
+
+/* memcpy(). */
+#include <string.h>
+
+/* errno. */
+#include <errno.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#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 <features.h> /* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+
+#include <config.h>
+
+/* Specification. */
+#undef ENABLE_RELOCATABLE /* avoid defining set_program_name as a macro */
+#include "progname.h"
+
+#include <errno.h> /* get program_invocation_name declaration */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* 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 "<dirname>/.libs/" or "<dirname>/.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 <dirname>/ 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+
+#define _GL_USE_STDLIB_ALLOC 1
+#include <config.h>
+
+/* Specification. */
+#include "progname.h"
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+/* Get declaration of _NSGetExecutablePath on Mac OS X 10.2 or newer. */
+#if HAVE_MACH_O_DYLD_H
+# include <mach-o/dyld.h>
+#endif
+
+#if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__
+# define WINDOWS_NATIVE
+#endif
+
+#ifdef WINDOWS_NATIVE
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#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 <stdlib.h> 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 <http://cygwin.com/ml/cygwin/2011-01/msg00410.html>). */
+ 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/<pid>/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/<pid>/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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+/* 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 <config.h>
+
+/* Specification. */
+#include "propername.h"
+
+#include <ctype.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if HAVE_ICONV
+# include <iconv.h>
+#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 <locale.h>
+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 <locale.h>
+# include <stdio.h>
+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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+/* 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:
+ <translated name> (<original name in English>)
+
+ 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 <http://www.gnu.org/licenses/>.
+
+ Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */
+
+#include <config.h>
+
+#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 <http://docs.sun.com/app/docs/doc/819-2241/6n4huc7ia?l=en&a=view>
+ 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 <http://www.gnu.org/licenses/>.
+
+ Written by Paul Eggert and Andreas Gruenbacher, and Bruno Haible. */
+
+#include <config.h>
+
+#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 <sys/acl.h> 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef QUOTE_H_
+# define QUOTE_H_ 1
+
+# include <stddef.h>
+
+/* The quoting options used by quote_n and quote. Its type is incomplete,
+ so it's useful only in expressions like '&quote_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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert <eggert@twinsun.com> */
+
+/* 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 <config.h>
+
+#include "quotearg.h"
+#include "quote.h"
+
+#include "xalloc.h"
+#include "c-strcaseeq.h"
+#include "localcharset.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#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
+ <http://en.wikipedia.org/wiki/Quotation_marks_in_other_languages>
+ 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, &quote_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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert <eggert@twinsun.com> */
+
+#ifndef QUOTEARG_H_
+# define QUOTEARG_H_ 1
+
+# include <stddef.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+/* written by Jim Meyering and Bruno Haible */
+
+#include <config.h>
+
+/* Specification. */
+#include <signal.h>
+
+#if HAVE_RAISE
+/* Native Windows platform. */
+
+# include <errno.h>
+
+# 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 <unistd.h>
+
+# 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <string.h>
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <unistd.h>
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+
+# include <errno.h>
+# include <io.h>
+
+# define WIN32_LEAN_AND_MEAN /* avoid including junk */
+# include <windows.h>
+
+# 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <dirent.h>
+
+#include <errno.h>
+#include <stddef.h>
+
+#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"
+ <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html>
+ "." 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <unistd.h>
+
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+/* written by Jim Meyering and Bruno Haible */
+
+#define _GL_USE_STDLIB_ALLOC 1
+#include <config.h>
+
+/* 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 <stdlib.h>
+
+#include <errno.h>
+
+/* 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 <http://www.gnu.org/licenses/>.
+#
+# Written by Bruno Haible <haible@clisp.cons.org>.
+#
+/^# 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 <http://www.gnu.org/licenses/>.
+#
+# Written by Bruno Haible <haible@clisp.cons.org>.
+#
+/^# 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+
+/* Tell glibc's <stdio.h> to provide a prototype for getline().
+ This must come before <config.h> because <config.h> may include
+ <features.h>, and once <features.h> has been included, it's too late. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+#define _GL_USE_STDLIB_ALLOC 1
+#include <config.h>
+
+/* Specification. */
+#include "relocatable.h"
+
+#if ENABLE_RELOCATABLE
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef NO_XMALLOC
+# define xmalloc malloc
+#else
+# include "xalloc.h"
+#endif
+
+#if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
+
+#if DEPENDS_ON_LIBCHARSET
+# include <libcharset.h>
+#endif
+#if DEPENDS_ON_LIBICONV && HAVE_ICONV
+# include <iconv.h>
+#endif
+#if DEPENDS_ON_LIBINTL && ENABLE_NLS
+# include <libintl.h>
+#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 <http://cygwin.com/ml/cygwin/2011-01/msg00410.html>). */
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+/* 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 <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include <unistd.h>
+
+#include <errno.h>
+#include <string.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#ifdef SAFE_WRITE
+# include "safe-write.h"
+#else
+# include "safe-read.h"
+#endif
+
+/* Get ssize_t. */
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <errno.h>
+
+#ifdef EINTR
+# define IS_EINTR(x) ((x) == EINTR)
+#else
+# define IS_EINTR(x) 0
+#endif
+
+#include <limits.h>
+
+#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
+ <http://lists.gnu.org/archive/html/bug-gnu-utils/2002-04/msg00010.html>.
+ 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 <http://www.gnu.org/licenses/>. */
+
+/* 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 <stddef.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#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 <http://www.gnu.org/licenses/>. */
+
+/* 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 <stddef.h>
+
+#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 <sched.h> 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 <http://www.gnu.org/licenses/>. */
+
+#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 <http://sourceware.org/bugzilla/show_bug.cgi?id=13198>)
+ and Mac OS X 10.5. */
+#include <sys/types.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#if !HAVE___SECURE_GETENV
+# if HAVE_ISSETUGID
+# include <unistd.h>
+# 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 <http://www.gnu.org/licenses/>.
+
+ Written by Paul Eggert and Andreas Gruenbacher, and Bruno Haible. */
+
+#include <config.h>
+
+#include "acl.h"
+
+#include <errno.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#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 <config.h>
+#endif
+
+#include <alloca.h>
+
+/* Specification. */
+#include <stdlib.h>
+
+#include <errno.h>
+#ifndef __set_errno
+# define __set_errno(ev) ((errno) = (ev))
+#endif
+
+#include <string.h>
+#if _LIBC || HAVE_UNISTD_H
+# include <unistd.h>
+#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 <bits/libc-lock.h>
+__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 <search.h>
+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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2009. */
+
+#include <config.h>
+
+/* 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 <locale.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "sh-quote.h"
+
+#include <string.h>
+
+#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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#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 <stddef.h>
+
+#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 <config.h>
+#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 <signal.h>.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _GL_SIG_HANDLER_H
+#define _GL_SIG_HANDLER_H
+
+#include <signal.h>
+
+#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 <ebb9@byu.net>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <signal.h>
+
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+/* 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 <signal.h>.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+#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
+ <signal.h> -> <ucontext.h> -> <signal.h>.
+ 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
+ <csignal> -> </usr/include/signal.h> -> <sys/ucontext.h> -> <signal.h>.
+ 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 <signal.h>, but in <sys/types.h>.
+ On Solaris 10, <signal.h> includes <sys/types.h>, which eventually includes
+ us; so include <sys/types.h> now, before the second inclusion guard. */
+#include <sys/types.h>
+
+/* 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 <pthread.h>, not in <signal.h>.
+ 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 <pthread.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. */
+
+/* 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.,
+ <http://lists.gnu.org/archive/html/bug-gnulib/2012-12/msg00023.html>.
+ 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <signal.h>
+
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#ifndef GNULIB_SIZE_MAX_H
+#define GNULIB_SIZE_MAX_H
+
+/* Get SIZE_MAX declaration on systems like Solaris 7/8/9. */
+# include <limits.h>
+/* Get SIZE_MAX declaration on systems like glibc 2. */
+# if HAVE_STDINT_H
+# include <stdint.h>
+# 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <stdio.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+
+#include <config.h>
+
+/* Specification. */
+#include "spawn-pipe.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+
+#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 <process.h>
+# include "w32spawn.h"
+
+#else
+
+/* Unix API. */
+# include <spawn.h>
+
+#endif
+
+/* environ is the exported symbol referencing the internal
+ __cygwin_environ variable on cygwin64:
+ <https://cygwin.com/ml/cygwin/2013-06/msg00228.html>. */
+#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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _SPAWN_PIPE_H
+#define _SPAWN_PIPE_H
+
+/* Get pid_t. */
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <stdbool.h>
+
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#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 <sched.h>
+# include <signal.h>
+#endif
+
+#include <sys/types.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <spawn.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <spawn.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <spawn.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <spawn.h>
+
+#include <stdlib.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <spawn.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <sys/types.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <spawn.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <spawn.h>
+
+#include <string.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <spawn.h>
+
+#include <errno.h>
+#include <string.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <spawn.h>
+
+#include <string.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <spawn.h>
+#include "spawn_int.h"
+
+#include <alloca.h>
+#include <errno.h>
+
+#include <fcntl.h>
+#ifndef O_LARGEFILE
+# define O_LARGEFILE 0
+#endif
+
+#if _LIBC || HAVE_PATHS_H
+# include <paths.h>
+#else
+# define _PATH_BSHELL "/bin/sh"
+#endif
+
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#if _LIBC
+# include <not-cancel.h>
+#else
+# define close_not_cancel close
+# define open_not_cancel open
+#endif
+
+#if _LIBC
+# include <local-setxid.h>
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <spawn.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+/* written by Eric Blake */
+
+/* If the user's config.h happens to include <sys/stat.h>, let it include only
+ the system's <sys/stat.h> here, so that orig_stat doesn't recurse to
+ rpl_stat. */
+#define __need_system_sys_stat_h
+#include <config.h>
+
+/* Get the original definition of stat. It might be defined as a macro. */
+#include <sys/types.h>
+#include <sys/stat.h>
+#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 <sys/stat.h>, otherwise OSF/1 5.1 DTK cc
+ eliminates this include because of the preliminary #include <sys/stat.h>
+ above. */
+#include "sys/stat.h"
+
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <string.h>
+#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 <stdarg.h>.
+ 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 <http://www.gnu.org/licenses/>. */
+
+#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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _GL_STDBOOL_H
+#define _GL_STDBOOL_H
+
+/* ISO C 99 <stdbool.h> for platforms that lack it. */
+
+/* Usage suggestions:
+
+ Programs that use <stdbool.h> should be aware of some limitations
+ and standards compliance issues.
+
+ Standards compliance:
+
+ - <stdbool.h> 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:
+
+ - <stdbool.h> 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 <sys/socket.h> 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 <OS.h> /* 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 <stdbool.h> 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 <stddef.h>, 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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Eric Blake. */
+
+/*
+ * POSIX 2008 <stddef.h> for platforms that have issues.
+ * <http://www.opengroup.org/susv3xbd/stddef.h.html>
+ */
+
+#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 <stddef.h> that blindly
+ redefines NULL even when __need_wint_t was defined, even though
+ wint_t is not normally provided by <stddef.h>. 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 <http://www.gnu.org/licenses/>. */
+
+/*
+ * ISO C 99 <stdint.h> for platforms that lack it.
+ * <http://www.opengroup.org/susv3xbd/stdint.h.html>
+ */
+
+#ifndef _@GUARD_PREFIX@_STDINT_H
+
+#if __GNUC__ >= 3
+@PRAGMA_SYSTEM_HEADER@
+#endif
+@PRAGMA_COLUMNS@
+
+/* When including a system file that in turn includes <inttypes.h>,
+ use the system <inttypes.h>, not our substitute. This avoids
+ problems with (for example) VMS, whose <sys/bitypes.h> includes
+ <inttypes.h>. */
+#define _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H
+
+/* On Android (Bionic libc), <sys/types.h> includes this file before
+ having defined 'time_t'. Therefore in this case avoid including
+ other system header files; just include the system's <stdint.h>.
+ Ideally we should test __BIONIC__ here, but it is only defined after
+ <sys/cdefs.h> 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 <stdint.h> 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 <stdint.h> 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 <stdint.h>.
+ Include it before <inttypes.h>, since any "#include <stdint.h>"
+ in <inttypes.h> 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
+
+/* <sys/types.h> defines some of the stdint.h types as well, on glibc,
+ IRIX 6.5, and OpenBSD 3.8 (via <machine/types.h>).
+ AIX 5.2 <sys/types.h> isn't needed and causes troubles.
+ Mac OS X 10.4.6 <sys/types.h> includes <stdint.h> (which is us), but
+ relies on the system <stdint.h> definitions, so include
+ <sys/types.h> after @NEXT_STDINT_H@. */
+#if @HAVE_SYS_TYPES_H@ && ! defined _AIX
+# include <sys/types.h>
+#endif
+
+/* Get SCHAR_MIN, SCHAR_MAX, UCHAR_MAX, INT_MIN, INT_MAX,
+ LONG_MIN, LONG_MAX, ULONG_MAX. */
+#include <limits.h>
+
+#if @HAVE_INTTYPES_H@
+ /* In OpenBSD 3.8, <inttypes.h> includes <machine/types.h>, which defines
+ int{8,16,32,64}_t, uint{8,16,32,64}_t and __BIT_TYPES_DEFINED__.
+ <inttypes.h> also defines intptr_t and uintptr_t. */
+# include <inttypes.h>
+#elif @HAVE_SYS_INTTYPES_H@
+ /* Solaris 7 <sys/inttypes.h> has the types except the *_fast*_t types, and
+ the macros except for *_FAST*_*, INTPTR_MIN, PTRDIFF_MIN, PTRDIFF_MAX. */
+# include <sys/inttypes.h>
+#endif
+
+#if @HAVE_SYS_BITYPES_H@ && ! defined __BIT_TYPES_DEFINED__
+ /* Linux libc4 >= 4.6.7 and libc5 have a <sys/bitypes.h> that defines
+ int{8,16,32,64}_t and __BIT_TYPES_DEFINED__. In libc5 >= 5.2.2 it is
+ included by <sys/types.h>. */
+# include <sys/bitypes.h>
+#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 <pthread.h> 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 <stdint.h> 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
+ <wchar.h> -> <stdio.h> -> <getopt.h> -> <stdlib.h>, and the latter includes
+ <stdint.h> 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: <stddef.h>, <stdio.h> and <time.h> must be
+ included before <wchar.h>. */
+# include <stddef.h>
+# include <stdio.h>
+# include <time.h>
+# define _GL_JUST_INCLUDE_SYSTEM_WCHAR_H
+# include <wchar.h>
+# 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <stdio.h>
+
+/* 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 <errno.h>
+# include <signal.h>
+# include <io.h>
+
+# define WIN32_LEAN_AND_MEAN /* avoid including junk */
+# include <windows.h>
+
+# 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 <stdio.h>.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+#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
+ <stdio.h> -> <getopt.h> -> <ctype.h> -> <sys/localedef.h> ->
+ <sys/lc_core.h> -> <nl_types.h> -> <mesg.h> -> <stdio.h>.
+ 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 <stdarg.h>
+
+#include <stddef.h>
+
+/* 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 <sys/types.h>
+
+/* 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 <unistd.h>, not in <stdio.h>. */
+/* But in any case avoid namespace pollution on glibc systems. */
+#if (@GNULIB_RENAMEAT@ || defined GNULIB_POSIXCHECK) && defined __sun \
+ && ! defined __GLIBC__
+# include <unistd.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. */
+
+/* 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.,
+ <http://lists.gnu.org/archive/html/bug-gnulib/2012-12/msg00023.html>.
+ 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
+ <http://sources.redhat.com/bugzilla/show_bug.cgi?id=11959>,
+ 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 <stdlib.h>.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+#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 <stddef.h>
+
+/* MirBSD 10 defines WEXITSTATUS in <sys/wait.h>, not in <stdlib.h>. */
+#if @GNULIB_SYSTEM_POSIX@ && !defined WEXITSTATUS
+# include <sys/wait.h>
+#endif
+
+/* Solaris declares getloadavg() in <sys/loadavg.h>. */
+#if (@GNULIB_GETLOADAVG@ || defined GNULIB_POSIXCHECK) && @HAVE_SYS_LOADAVG_H@
+# include <sys/loadavg.h>
+#endif
+
+/* Native Windows platforms declare mktemp() in <io.h>. */
+#if 0 && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)
+# include <io.h>
+#endif
+
+#if @GNULIB_RANDOM_R@
+
+/* OSF/1 5.1 declares 'struct random_data' in <random.h>, which is included
+ from <stdlib.h> if _REENTRANT is defined. Include it whenever we need
+ 'struct random_data'. */
+# if @HAVE_RANDOM_H@
+# include <random.h>
+# endif
+
+# if !@HAVE_STRUCT_RANDOM_DATA@ || @REPLACE_RANDOM_R@ || !@HAVE_RANDOM_R@
+# include <stdint.h>
+# endif
+
+# if !@HAVE_STRUCT_RANDOM_DATA@
+/* Define 'struct random_data'.
+ But allow multiple gnulib generated <stdlib.h> 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 <unistd.h> declares mkstemp. */
+/* On Mac OS X 10.5, only <unistd.h> declares mkstemps. */
+/* On Cygwin 1.7.1, only <unistd.h> declares getsubopt. */
+/* But avoid namespace pollution on glibc systems and native Windows. */
+# include <unistd.h>
+#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 <fcntl.h>)
+ 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 <fcntl.h>)
+ 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include <string.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+/* This is almost copied from strncpy.c, written by Torbjorn Granlund. */
+
+#include <config.h>
+
+/* Specification. */
+#include <string.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+/* 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 <ebb9@byu.net>, 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 <http://www.gnu.org/licenses/>. */
+
+/* Before including this file, you need to include <config.h> and
+ <string.h>, 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 <limits.h>
+#include <stdint.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <string.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <string.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>. */
+
+#ifndef _GL_STREQ_H
+#define _GL_STREQ_H
+
+#include <string.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2010. */
+
+#include <config.h>
+
+#include "strerror-override.h"
+
+#include <errno.h>
+
+#if GNULIB_defined_EWINSOCK /* native Windows platforms */
+# if HAVE_WINSOCK2_H
+# include <winsock2.h>
+# 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 <errno.h> */
+ 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 <errno.h> */
+ 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _GL_STRERROR_OVERRIDE_H
+# define _GL_STRERROR_OVERRIDE_H
+
+# include <errno.h>
+# include <stddef.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <string.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "striconv.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if HAVE_ICONV
+# include <iconv.h>
+/* Get MB_LEN_MAX, CHAR_BIT. */
+# include <limits.h>
+#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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _STRICONV_H
+#define _STRICONV_H
+
+#include <stddef.h>
+#if HAVE_ICONV
+#include <iconv.h>
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "striconveh.h"
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if HAVE_ICONV
+# include <iconv.h>
+# 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _STRICONVEH_H
+#define _STRICONVEH_H
+
+#include <stddef.h>
+#if HAVE_ICONV
+#include <iconv.h>
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "striconveha.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _STRICONVEHA_H
+#define _STRICONVEHA_H
+
+#include <stdbool.h>
+#include <stddef.h>
+
+#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 <string.h>.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+#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 <stddef.h>
+
+/* MirBSD defines mbslen as a macro. */
+#if @GNULIB_MBSLEN@ && defined __MirBSD__
+# include <wchar.h>
+#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 <unistd.h>, not in <string.h>. */
+/* But in any case avoid namespace pollution on glibc systems. */
+#if (@GNULIB_STRSIGNAL@ || defined GNULIB_POSIXCHECK) && defined __NetBSD__ \
+ && ! defined __GLIBC__
+# include <unistd.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. */
+
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include <string.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "strnlen1.h"
+
+#include <string.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _STRNLEN1_H
+#define _STRNLEN1_H
+
+#include <stddef.h>
+
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <string.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+/* This particular implementation was written by Eric Blake, 2008. */
+
+#ifndef _LIBC
+# include <config.h>
+#endif
+
+/* Specification of strstr. */
+#include <string.h>
+
+#include <stdbool.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#ifdef _LIBC
+# define USE_NUMBER_GROUPING
+#else
+# include <config.h>
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#ifndef __set_errno
+# define __set_errno(Val) errno = (Val)
+#endif
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <wchar.h>
+# include <wctype.h>
+# 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 <locale.h>. */
+ 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 <http://www.gnu.org/licenses/>. */
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#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 <sys/select.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 <http://www.gnu.org/licenses/>. */
+
+# if __GNUC__ >= 3
+@PRAGMA_SYSTEM_HEADER@
+# endif
+@PRAGMA_COLUMNS@
+
+/* On OSF/1 and Solaris 2.6, <sys/types.h> and <sys/time.h>
+ both include <sys/select.h>.
+ On Cygwin, <sys/time.h> includes <sys/select.h>.
+ 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, <sys/timespec.h> includes <sys/types.h>, which includes
+ <sys/bsd_types.h>, which includes <sys/select.h>. At this point we cannot
+ include <signal.h>, because that includes <internal/signal_core.h>, which
+ gives a syntax error because <sys/timespec.h> 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, <pthread.h> includes <sys/types.h>, which includes
+ <sys/select.h>. At this point we cannot include <signal.h>, 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, <sys/select.h> assumes prior inclusion of
+ <sys/types.h>. Also, mingw defines sigset_t there, instead of
+ in <signal.h> where it belongs. */
+#include <sys/types.h>
+
+#if @HAVE_SYS_SELECT_H@
+
+/* On OSF/1 4.0, <sys/select.h> 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 <sys/time.h>.
+ But avoid namespace pollution on glibc systems. */
+# ifndef __GLIBC__
+# include <sys/time.h>
+# endif
+
+/* On AIX 7 and Solaris 10, <sys/select.h> provides an FD_ZERO implementation
+ that relies on memset(), but without including <string.h>.
+ But in any case avoid namespace pollution on glibc systems. */
+# if (defined __OpenBSD__ || defined _AIX || defined __sun || defined __osf__ || defined __BEOS__) \
+ && ! defined __GLIBC__
+# include <string.h>
+# 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 <signal.h>
+#endif
+
+#ifndef _@GUARD_PREFIX@_SYS_SELECT_H
+#define _@GUARD_PREFIX@_SYS_SELECT_H
+
+#if !@HAVE_SYS_SELECT_H@
+/* A platform that lacks <sys/select.h>. */
+/* Get the 'struct timeval' and 'fd_set' types and the FD_* macros
+ on most platforms. */
+# include <sys/time.h>
+/* On HP-UX 11, <sys/time.h> provides an FD_ZERO implementation
+ that relies on memset(), but without including <string.h>. */
+# if defined __hpux
+# include <string.h>
+# 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 <winsock2.h>
+# undef _GL_INCLUDING_WINSOCK2_H
+# endif
+# include <io.h>
+# 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 <winsock2.h>. */
+
+#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 <winsock2.h>. */
+
+#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 <unistd.h>");
+# 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 <unistd.h>");
+# 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 <sys/socket.h>");
+ _GL_WARN_ON_USE (connect,
+ "connect() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (accept,
+ "accept() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (bind,
+ "bind() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (getpeername,
+ "getpeername() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (getsockname,
+ "getsockname() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (getsockopt,
+ "getsockopt() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (listen,
+ "listen() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (recv,
+ "recv() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (send,
+ "send() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (recvfrom,
+ "recvfrom() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (sendto,
+ "sendto() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (setsockopt,
+ "setsockopt() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (shutdown,
+ "shutdown() used without including <sys/socket.h>");
+# 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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Eric Blake, Paul Eggert, and Jim Meyering. */
+
+/* This file is supposed to be used on platforms where <sys/stat.h> 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 <sys/types.h>
+
+/* Get struct timespec. */
+#include <time.h>
+
+/* 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 <io.h> and/or <direct.h>, not in <unistd.h>. */
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# include <io.h> /* mingw32, mingw64 */
+# include <direct.h> /* mingw64, MSVC 9 */
+#endif
+
+/* Native Windows platforms declare umask() in <io.h>. */
+#if 0 && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)
+# include <io.h>
+#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 <direct.h> and <io.h>,
+ 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 <http://www.gnu.org/licenses/>. */
+
+/* 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, <sys/time.h> includes itself
+ recursively via <sys/select.h>.
+ 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 <sys/time.h>. */
+#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 <time.h>
+#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 <winsock2.h>
+# 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 <winsock2.h>. */
+
+#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 <unistd.h>");
+# 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 <unistd.h>");
+# 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 <sys/socket.h>");
+ _GL_WARN_ON_USE (connect,
+ "connect() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (accept,
+ "accept() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (bind,
+ "bind() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (getpeername,
+ "getpeername() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (getsockname,
+ "getsockname() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (getsockopt,
+ "getsockopt() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (listen,
+ "listen() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (recv,
+ "recv() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (send,
+ "send() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (recvfrom,
+ "recvfrom() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (sendto,
+ "sendto() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (setsockopt,
+ "setsockopt() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (shutdown,
+ "shutdown() used without including <sys/socket.h>");
+# 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 <sys/select.h>");
+# 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 <http://www.gnu.org/licenses/>. */
+
+#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 <stdint.h>. */
+# 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 <stddef.h>, not in <sys/types.h>. */
+/* But avoid namespace pollution on glibc systems. */
+#if ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) \
+ && ! defined __GLIBC__
+# include <stddef.h>
+#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 <sys/wait.h>.
+ 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 <http://www.gnu.org/licenses/>. */
+
+
+#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 <sys/types.h>
+
+
+/* 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 <signal.h> /* 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 <http://www.gnu.org/licenses/>. */
+
+/* Extracted from glibc sysdeps/posix/tempname.c. See also tmpdir.c. */
+
+#if !_LIBC
+# include <config.h>
+# include "tempname.h"
+#endif
+
+#include <sys/types.h>
+#include <assert.h>
+
+#include <errno.h>
+#ifndef __set_errno
+# define __set_errno(Val) errno = (Val)
+#endif
+
+#include <stdio.h>
+#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 <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <fcntl.h>
+#include <sys/time.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include <sys/stat.h>
+
+#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 <hp-timing.h>
+# 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 <http://www.gnu.org/licenses/>. */
+
+/* header written by Eric Blake */
+
+#ifndef GL_TEMPNAME_H
+# define GL_TEMPNAME_H
+
+# include <stdio.h>
+
+# 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "term-ostream.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "term-ostream.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "term-styled-ostream.h"
+
+#include <stdlib.h>
+
+#include <cr-om-parser.h>
+#include <cr-sel-eng.h>
+#include <cr-style.h>
+#include <cr-rgb.h>
+/* <cr-fonts.h> has a broken double-inclusion guard in libcroco-0.6.1. */
+#ifndef __CR_FONTS_H__
+# include <cr-fonts.h>
+#endif
+#include <cr-string.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "term-styled-ostream.h"
+
+#include <stdlib.h>
+
+#include <cr-om-parser.h>
+#include <cr-sel-eng.h>
+#include <cr-style.h>
+#include <cr-rgb.h>
+/* <cr-fonts.h> has a broken double-inclusion guard in libcroco-0.6.1. */
+#ifndef __CR_FONTS_H__
+# include <cr-fonts.h>
+#endif
+#include <cr-string.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _TERMINFO_H
+#define _TERMINFO_H
+
+/* Including <curses.h> or <term.h> 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 <termcap.h>. */
+
+/* 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 <term.h>, <curses.h>, <ncurses.h>,
+ - OSF/1 curses in <term.h>, <curses.h>,
+ - Solaris, AIX, HP-UX, IRIX curses in <term.h>,
+ - 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 <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 <http://www.gnu.org/licenses/>. */
+
+#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 <time.h> eventually includes itself
+ recursively; if that is happening, just include the system <time.h>
+ 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 <stddef.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. */
+
+/* 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 <sys/time.h>
+ (e.g., FreeBSD circa 1997). Stock Mingw prior to 3.0 does not define it,
+ but the pthreads-win32 library defines it in <pthread.h>. */
+# if ! @TIME_H_DEFINES_STRUCT_TIMESPEC@
+# if @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@
+# include <sys/time.h>
+# elif @PTHREAD_H_DEFINES_STRUCT_TIMESPEC@
+# include <pthread.h>
+# 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
+ <http://www.opengroup.org/susv3xsh/nanosleep.html>. */
+# 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
+ <http://www.opengroup.org/susv3xsh/localtime_r.html> and
+ <http://www.opengroup.org/susv3xsh/gmtime_r.html>. */
+# 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
+ <http://www.opengroup.org/susv3xsh/localtime.html> and
+ <http://www.opengroup.org/susv3xsh/gmtime.html>. */
+# 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
+ <http://www.opengroup.org/susv3xsh/strptime.html>. */
+# 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 <http://www.gnu.org/licenses/>. */
+
+/* Extracted from sysdeps/posix/tempname.c. */
+
+#include <config.h>
+
+/* Specification. */
+#include "tmpdir.h"
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <errno.h>
+#ifndef __set_errno
+# define __set_errno(Val) errno = (Val)
+#endif
+
+#include <stdio.h>
+#ifndef P_tmpdir
+# ifdef _P_tmpdir /* native Windows */
+# define P_tmpdir _P_tmpdir
+# else
+# define P_tmpdir "/tmp"
+# endif
+#endif
+
+#include <sys/stat.h>
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# define WIN32_LEAN_AND_MEAN /* avoid including junk */
+# include <windows.h>
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <stdbool.h>
+#include <stddef.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+/* Originally by Ross Ridge, Public Domain, 92/02/01 07:30:36 */
+
+#include <config.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Davide Angelocola <davide.angelocola@gmail.com> */
+
+#include <config.h>
+
+/* Specification. */
+#include "trim.h"
+
+#include <ctype.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Davide Angelocola <davide.angelocola@gmail.com> */
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _UNICONV_H
+#define _UNICONV_H
+
+/* Get size_t. */
+#include <stddef.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "uniconv.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _UNILBRK_H
+#define _UNILBRK_H
+
+/* Get size_t. */
+#include <stddef.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#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 <http://www.gnu.org/licenses/>. */
+
+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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* 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
+ "<P>Some sentence.</P>" */
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "unilbrk.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#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 <stdio.h>
+#include <string.h>
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+/* Get size_t. */
+#include <stddef.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "unilbrk.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#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 <stdio.h>
+#include <locale.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "uniname.h"
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert. */
+
+#include <unistd.h>
+#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 <http://www.gnu.org/licenses/>. */
+
+/* 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 <config.h>
+#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 <unistd.h>.
+ 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 <http://www.gnu.org/licenses/>. */
+
+#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
+ <unistd.h> -> <signal.h> -> <pthread.h> -> <unistd.h>
+ 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 <winsock2.h>
+# 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 <stddef.h>
+
+/* mingw doesn't define the SEEK_* or *_FILENO macros in <unistd.h>. */
+/* Cygwin 1.7.1 declares symlinkat in <stdio.h>, not in <unistd.h>. */
+/* 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 <stdio.h>
+#endif
+
+/* Cygwin 1.7.1 declares unlinkat in <fcntl.h>, not in <unistd.h>. */
+/* But avoid namespace pollution on glibc systems. */
+#if (@GNULIB_UNLINKAT@ || defined GNULIB_POSIXCHECK) && defined __CYGWIN__ \
+ && ! defined __GLIBC__
+# include <fcntl.h>
+#endif
+
+/* mingw fails to declare _exit in <unistd.h>. */
+/* mingw, MSVC, BeOS, Haiku declare environ in <stdlib.h>, not in
+ <unistd.h>. */
+/* Solaris declares getcwd not only in <unistd.h> but also in <stdlib.h>. */
+/* OSF Tru64 Unix cannot see gnulib rpl_strtod when system <stdlib.h> is
+ included here. */
+/* But avoid namespace pollution on glibc systems. */
+#if !defined __GLIBC__ && !defined __osf__
+# define __need_system_stdlib_h
+# include <stdlib.h>
+# undef __need_system_stdlib_h
+#endif
+
+/* Native Windows platforms declare chdir, getcwd, rmdir in
+ <io.h> and/or <direct.h>, not in <unistd.h>.
+ They also declare access(), chmod(), close(), dup(), dup2(), isatty(),
+ lseek(), read(), unlink(), write() in <io.h>. */
+#if ((@GNULIB_CHDIR@ || @GNULIB_GETCWD@ || @GNULIB_RMDIR@ \
+ || defined GNULIB_POSIXCHECK) \
+ && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__))
+# include <io.h> /* mingw32, mingw64 */
+# include <direct.h> /* 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 <io.h>
+#endif
+
+/* AIX and OSF/1 5.1 declare getdomainname in <netdb.h>, not in <unistd.h>.
+ NonStop Kernel declares gethostname in <netdb.h>, not in <unistd.h>. */
+/* But avoid namespace pollution on glibc systems. */
+#if ((@GNULIB_GETDOMAINNAME@ && (defined _AIX || defined __osf__)) \
+ || (@GNULIB_GETHOSTNAME@ && defined __TANDEM)) \
+ && !defined __GLIBC__
+# include <netdb.h>
+#endif
+
+/* MSVC defines off_t in <sys/types.h>.
+ 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 <sys/types.h>
+#endif
+
+#if (@GNULIB_READ@ || @GNULIB_WRITE@ \
+ || @GNULIB_READLINK@ || @GNULIB_READLINKAT@ \
+ || @GNULIB_PREAD@ || @GNULIB_PWRITE@ || defined GNULIB_POSIXCHECK)
+/* Get ssize_t. */
+# include <sys/types.h>
+#endif
+
+/* Get getopt(), optarg, optind, opterr, optopt.
+ But avoid namespace pollution on glibc systems. */
+/* Also, don't include <getopt.h> 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 <getopt.h>
+#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 <winsock2.h>. */
+
+#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 <sys/socket.h>");
+ _GL_WARN_ON_USE (connect,
+ "connect() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (accept,
+ "accept() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (bind,
+ "bind() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (getpeername,
+ "getpeername() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (getsockname,
+ "getsockname() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (getsockopt,
+ "getsockopt() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (listen,
+ "listen() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (recv,
+ "recv() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (send,
+ "send() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (recvfrom,
+ "recvfrom() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (sendto,
+ "sendto() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (setsockopt,
+ "setsockopt() used without including <sys/socket.h>");
+ _GL_WARN_ON_USE (shutdown,
+ "shutdown() used without including <sys/socket.h>");
+# 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 <sys/select.h>");
+# 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 <unistd.h> - "
+ "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
+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/chown.html. */
+# if @REPLACE_CHOWN@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef chown
+# define chown rpl_chown
+# endif
+_GL_FUNCDECL_RPL (chown, int, (const char *file, uid_t uid, gid_t gid)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (chown, int, (const char *file, uid_t uid, gid_t gid));
+# else
+# if !@HAVE_CHOWN@
+_GL_FUNCDECL_SYS (chown, int, (const char *file, uid_t uid, gid_t gid)
+ _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (chown, int, (const char *file, uid_t uid, gid_t gid));
+# endif
+_GL_CXXALIASWARN (chown);
+#elif defined GNULIB_POSIXCHECK
+# undef chown
+# if HAVE_RAW_DECL_CHOWN
+_GL_WARN_ON_USE (chown, "chown fails to follow symlinks on some systems and "
+ "doesn't treat a uid or gid of -1 on some systems - "
+ "use gnulib module chown for portability");
+# endif
+#endif
+
+
+#if @GNULIB_CLOSE@
+# if @REPLACE_CLOSE@
+/* Automatically included by modules that need a replacement for close. */
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef close
+# define close rpl_close
+# endif
+_GL_FUNCDECL_RPL (close, int, (int fd));
+_GL_CXXALIAS_RPL (close, int, (int fd));
+# else
+_GL_CXXALIAS_SYS (close, int, (int fd));
+# endif
+_GL_CXXALIASWARN (close);
+#elif @UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS@
+# undef close
+# define close close_used_without_requesting_gnulib_module_close
+#elif defined GNULIB_POSIXCHECK
+# undef close
+/* Assume close is always declared. */
+_GL_WARN_ON_USE (close, "close does not portably work on sockets - "
+ "use gnulib module close for portability");
+#endif
+
+
+#if @GNULIB_DUP@
+# if @REPLACE_DUP@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# define dup rpl_dup
+# endif
+_GL_FUNCDECL_RPL (dup, int, (int oldfd));
+_GL_CXXALIAS_RPL (dup, int, (int oldfd));
+# else
+_GL_CXXALIAS_SYS (dup, int, (int oldfd));
+# endif
+_GL_CXXALIASWARN (dup);
+#elif defined GNULIB_POSIXCHECK
+# undef dup
+# if HAVE_RAW_DECL_DUP
+_GL_WARN_ON_USE (dup, "dup is unportable - "
+ "use gnulib module dup for portability");
+# endif
+#endif
+
+
+#if @GNULIB_DUP2@
+/* Copy the file descriptor OLDFD into file descriptor NEWFD. Do nothing if
+ NEWFD = OLDFD, otherwise close NEWFD first if it is open.
+ Return newfd if successful, otherwise -1 and errno set.
+ See the POSIX:2008 specification
+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/dup2.html>. */
+# 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 <fcntl.h>)
+ 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
+ <http://www.kernel.org/doc/man-pages/online/pages/man2/dup3.2.html>. */
+# 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 <TargetConditionals.h>
+# if !TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
+# define _GL_USE_CRT_EXTERNS
+# endif
+# endif
+# ifdef _GL_USE_CRT_EXTERNS
+# include <crt_externs.h>
+# 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
+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchdir.html>. */
+# 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
+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html>. */
+# 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
+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html>. */
+# 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
+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html>. */
+# 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
+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/getcwd.html>.
+ 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 <http://www.opengroup.org/susv3xsh/getlogin.html>.
+
+ 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 <http://www.opengroup.org/susv3xsh/getlogin.html>.
+
+ 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 <OS.h>
+# 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 <sys/param.h>
+# 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
+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/lchown.html>. */
+# 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
+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/link.html>. */
+# 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
+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html>. */
+# 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 <fcntl.h>)
+ 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
+ <http://www.kernel.org/doc/man-pages/online/pages/man2/pipe2.2.html>. */
+# 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
+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/pread.html>. */
+# 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
+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/pwrite.html>. */
+# 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
+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html>. */
+# 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
+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html>. */
+# 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
+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/sleep.html>. */
+# 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
+ <http://www.opengroup.org/susv3xsh/usleep.html>. */
+# 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
+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html>. */
+# 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _UNISTR_H
+#define _UNISTR_H
+
+#include "unitypes.h"
+
+/* Get common macros for C. */
+#include "unused-parameter.h"
+
+/* Get bool. */
+#include <stdbool.h>
+
+/* Get size_t. */
+#include <stddef.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _UNITYPES_H
+#define _UNITYPES_H
+
+/* Get uint8_t, uint16_t, uint32_t. */
+#include <stdint.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _UNIWIDTH_H
+#define _UNIWIDTH_H
+
+#include "unitypes.h"
+
+/* Get size_t. */
+#include <stddef.h>
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+/* 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 <stdio.h>
+
+# 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 <http://www.gnu.org/licenses/>. */
+
+/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
+ optimizes away the name == NULL test below. */
+#define _GL_ARG_NONNULL(params)
+
+#include <config.h>
+
+/* Specification. */
+#include <stdlib.h>
+
+#include <errno.h>
+#if !_LIBC
+# define __set_errno(ev) ((errno) = (ev))
+#endif
+
+#include <string.h>
+#include <unistd.h>
+
+#if !_LIBC
+# define __environ environ
+#endif
+
+#if _LIBC
+/* This lock protects against simultaneous modifications of 'environ'. */
+# include <bits/libc-lock.h>
+__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 <http://www.gnu.org/licenses/>. */
+
+/* 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 <stdio.h> to provide a prototype for snprintf().
+ This must come before <config.h> because <config.h> may include
+ <features.h>, and once <features.h> has been included, it's too late. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+#ifndef VASNPRINTF
+# include <config.h>
+#endif
+#ifndef IN_LIBINTL
+# include <alloca.h>
+#endif
+
+/* Specification. */
+#ifndef VASNPRINTF
+# if WIDE_CHAR_VERSION
+# include "vasnwprintf.h"
+# else
+# include "vasnprintf.h"
+# endif
+#endif
+
+#include <locale.h> /* localeconv() */
+#include <stdio.h> /* snprintf(), sprintf() */
+#include <stdlib.h> /* abort(), malloc(), realloc(), free() */
+#include <string.h> /* memcpy(), strlen() */
+#include <errno.h> /* errno */
+#include <limits.h> /* CHAR_BIT */
+#include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */
+#if HAVE_NL_LANGINFO
+# include <langinfo.h>
+#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 <math.h>
+# include "float+.h"
+#endif
+
+#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
+# include <math.h>
+# include "isnand-nolibm.h"
+#endif
+
+#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) && !defined IN_LIBINTL
+# include <math.h>
+# include "isnanl-nolibm.h"
+# include "fpucw.h"
+#endif
+
+#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
+# include <math.h>
+# include "isnand-nolibm.h"
+# include "printf-frexp.h"
+#endif
+
+#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
+# include <math.h>
+# 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, then q:=0 and r:=a.
+ 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<b[0]<beta}
+ j:=j-1, r:=r*beta+a[j], q[j]:=floor(r/b[0]), r:=r-b[0]*q[j].
+ Normalise [q[m-1],...,q[0]], yields q.
+ If m>=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<intDsize.
+ Shift a and b left by s bits, copying them. r:=a.
+ r=[r[m],...,r[0]], b=[b[n-1],...,b[0]] with b[n-1]>=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<n: trivial case. q=0, r := copy of a. */
+ r_ptr = roomptr;
+ r_len = a_len;
+ memcpy (r_ptr, a_ptr, a_len * sizeof (mp_limb_t));
+ q_ptr = roomptr + a_len;
+ q_len = 0;
+ }
+ else if (b_len == 1)
+ {
+ /* n=1: single precision division.
+ beta^(m-1) <= a < beta^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, <beta). */
+ {
+ mp_twolimb_t c2 = /* c1*beta+r[j+n-2] */
+ ((mp_twolimb_t) c1 << GMP_LIMB_BITS) | r_ptr[j + b_len - 2];
+ mp_twolimb_t c3 = /* b[n-2] * q* */
+ (mp_twolimb_t) b_2msd * (mp_twolimb_t) q_star;
+ /* While c2 < c3, increase c2 and decrease c3.
+ Consider c3-c2. While it is > 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
+ <http://gcc.gnu.org/ml/gcc/2007-06/msg00122.html> and
+ <http://msdn2.microsoft.com/en-us/library/ms175782(VS.80).aspx>
+ 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _VASNPRINTF_H
+#define _VASNPRINTF_H
+
+/* Get va_list. */
+#include <stdarg.h>
+
+/* Get size_t. */
+#include <stddef.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#ifdef IN_LIBASPRINTF
+# include "vasprintf.h"
+#else
+# include <stdio.h>
+#endif
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+/* 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 <sys/cdefs.h>, included by <stddef.h> 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 <stddef.h>
+# 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 <int w>
+ 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 <yoann@prelude-ids.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, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification. */
+#include <stdio.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+/* Get declarations of the native Windows API functions. */
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+/* Get _open_osfhandle(). */
+#include <io.h>
+
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+/* 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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+
+#include <config.h>
+
+/* Specification. */
+#include "wait-process.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#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 <windows.h>
+
+/* 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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _WAIT_PROCESS_H
+#define _WAIT_PROCESS_H
+
+/* Get pid_t. */
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <stdbool.h>
+
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <sys/wait.h>
+
+/* Implementation for native Windows systems. */
+
+#include <process.h> /* 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 <wchar.h>, 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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Eric Blake. */
+
+/*
+ * ISO C 99 <wchar.h> for platforms that have issues.
+ * <http://www.opengroup.org/susv3xbd/wchar.h.html>
+ *
+ * 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
+ <wchar.h> -> <stdlib.h> -> <stdint.h>, and the latter includes <wchar.h>,
+ once indirectly <stdint.h> -> <sys/types.h> -> <inttypes.h> -> <wchar.h>
+ 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 <wchar.h>.
+ - On IRIX 6.5, similarly, we have an include <wchar.h> -> <wctype.h>, and
+ the latter includes <wchar.h>. But here, we have no way to detect whether
+ <wctype.h> 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 <features.h> /* for __GLIBC__ */
+#endif
+
+/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
+ <wchar.h>.
+ BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
+ included before <wchar.h>.
+ In some builds of uClibc, <wchar.h> is nonexistent and wchar_t is defined
+ by <stddef.h>.
+ But avoid namespace pollution on glibc systems. */
+#if !(defined __GLIBC__ && !defined __UCLIBC__)
+# include <stddef.h>
+#endif
+#ifndef __GLIBC__
+# include <stdio.h>
+# include <time.h>
+#endif
+
+/* Include the original <wchar.h> 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 <crtdefs.h>.
+ 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 <crtdefs.h>
+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 <config.h>
+#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 <wctype.h>, 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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible and Paul Eggert. */
+
+/*
+ * ISO C 99 <wctype.h> for platforms that lack it.
+ * <http://www.opengroup.org/susv3xbd/wctype.h.html>
+ *
+ * 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: <wchar.h> must be included before <wctype.h>.
+ Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
+ <wchar.h>.
+ BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
+ included before <wchar.h>. */
+# include <stddef.h>
+# include <stdio.h>
+# include <time.h>
+# include <wchar.h>
+#endif
+
+/* mingw has declarations of towupper and towlower in <ctype.h> as
+ well <wctype.h>. Include <ctype.h> in advance to avoid rpl_ prefix
+ being added to the declarations. */
+#ifdef __MINGW32__
+# include <ctype.h>
+#endif
+
+/* Include the original <wctype.h> if it exists.
+ BeOS 5 has the functions but no <wctype.h>. */
+/* 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 <wctype.h> includes <widec.h> which includes <euc.h> 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 <crtdefs.h>.
+ 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 <crtdefs.h>
+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 <wctype.h> but lacks the functions.
+ Linux libc5 has <wctype.h> 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 <ctype.h> 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 <wctype.h> 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <wchar.h>
+
+/* Get iswprint. */
+#include <wctype.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <unistd.h>
+
+/* 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 <errno.h>
+# include <signal.h>
+# include <io.h>
+
+# define WIN32_LEAN_AND_MEAN /* avoid including junk */
+# include <windows.h>
+
+# 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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _XALLOC_H
+#define _XALLOC_H
+
+#include <stddef.h>
+
+
+#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 <typename T>
+ 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 <typename T>
+ 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <haible@clisp.cons.org>. */
+
+#include <config.h>
+
+/* 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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+
+#include <config.h>
+
+/* Specification. */
+#include "xerror.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <haible@clisp.cons.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "xalloc.h"
+
+#include <stdlib.h>
+
+#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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* 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 <bruno@clisp.org>, 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 <http://www.gnu.org/licenses/>. */
+
+#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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Jim Meyering <jim@meyering.net>
+ and Bruno Haible <bruno@clisp.org>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "xreadlink.h"
+
+#include <errno.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Jim Meyering <jim@meyering.net> */
+
+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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "xsetenv.h"
+
+#include <stdlib.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+/* Get unsetenv(). It can be used without error checking. */
+#include <stdlib.h>
+
+#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 <config.h>
+#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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _XSIZE_H
+#define _XSIZE_H
+
+/* Get size_t. */
+#include <stddef.h>
+
+/* Get SIZE_MAX. */
+#include <limits.h>
+#if HAVE_STDINT_H
+# include <stdint.h>
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "xalloc.h"
+
+#include <string.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "xstriconv.h"
+
+#include <errno.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _XSTRICONV_H
+#define _XSTRICONV_H
+
+#include <stddef.h>
+#if HAVE_ICONV
+#include <iconv.h>
+#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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "xstriconveh.h"
+
+#include <errno.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _XSTRICONVEH_H
+#define _XSTRICONVEH_H
+
+#include <stddef.h>
+
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "xvasprintf.h"
+
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+#include <stdio.h>
+
+#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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _XVASPRINTF_H
+#define _XVASPRINTF_H
+
+/* Get va_list. */
+#include <stdarg.h>
+
+/* 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 */